Java HttpServletRequest.getParameterValues() 中的值排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2317281/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 06:03:03  来源:igfitidea点击:

Ordering of values in HttpServletRequest.getParameterValues()

javahttpservlets

提问by skaffman

HttpServletRequest.getParameterValues()returns a String[]containing all values of a given HTTP request parameter. Does anyone know if the order of the values in this array is guaranteed by specification to by the same as the order which those values were passed through in the request?

HttpServletRequest.getParameterValues()返回String[]包含给定 HTTP 请求参数的所有值的 。有谁知道这个数组中值的顺序是否由规范保证与这些值在请求中传递的顺序相同?

For example, if I have the GET query string x=1&x=2&x=3, am I guaranteedto receive the String[] {"1", "2", "3"}when I call getParameterValues()? It seems to work in practice, but I can't find anything which specifies that this must be the case, so I'm reluctant to rely on it.

例如,如果我有 GET 查询字符串x=1&x=2&x=3,我能保证String[] {"1", "2", "3"}在我打电话时收到getParameterValues()吗?它似乎在实践中有效,但我找不到任何说明必须是这种情况的内容,所以我不愿意依赖它。

采纳答案by brabster

The javadoc for ServletRequest (v2.5 javadoc) does not mention anything about the ordering of values for that method. As such, I wouldn't rely on the order being preserved.

ServletRequest ( v2.5 javadoc) 的javadoc没有提到有关该方法的值排序的任何内容。因此,我不会依赖保留的顺序。



Update: also checked the spec document for 2.5, contains the following information relating to getParameterValues(). It does not mention anything about ordering with respect to the query string, so I think the behaviour you are seeing is implementation detail, not defined as part of the interface.

更新:还检查了 2.5 的规范文档,包含与 getParameterValues() 相关的以下信息。它没有提到关于查询字符串的任何排序,所以我认为你看到的行为是实现细节,而不是定义为接口的一部分。

The parameters are stored as a set of name-value pairs. Multiple parameter values can exist for any given parameter name. The following methods of the ServletRequest interface are available to access parameters:

参数存储为一组名称-值对。任何给定的参数名称都可以存在多个参数值。ServletRequest 接口的以下方法可用于访问参数:

  • getParameter
  • getParameterNames
  • getParameterValues
  • getParameterMap
  • 获取参数
  • 获取参数名称
  • 获取参数值
  • 获取参数映射

The getParameterValues method returns an array of String objects containing all the parameter values associated with a parameter name. The value returned from the getParameter method must be the first value in the array of String objects returned by getParameterValues. The getParameterMap method returns a java.util.Map of the parameter of the request, which contains names as keys and parameter values as map values.

getParameterValues 方法返回一个 String 对象数组,其中包含与参数名称关联的所有参数值。getParameter 方法返回的值必须是 getParameterValues 返回的 String 对象数组中的第一个值。getParameterMap 方法返回请求参数的 java.util.Map,其中包含名称作为键和参数值作为映射值。

For future reference, the Java Servlet specs can be downloaded from Sun, I mean Oracle's website. You can double check the specific servlet version you're interested in there.

为了将来参考,Java Servlet 规范可以从Sun下载,我指的是 Oracle 的网站。您可以在那里仔细检查您感兴趣的特定 servlet 版本。

回答by BalusC

It's indeed not explicitly definied in the Servlet spec, but at least the HTML forms spec definies it explicitly in the application/x-www-form-urlencodedsection:

它确实没有在 Servlet 规范中明确定义,但至少 HTML 表单规范在application/x-www-form-urlencoded部分明确定义了它:

2.The control names/values are listed in the order they appear in the document.

2.控件名称/值按它们在文档中出现的顺序列出。

So, that part is safe. Now the servletcontainer, most logically a decent and efficient implementation would process the HTTP input stream immediately as it comes in, so the parameters would be processed in the order as they appear in the request URI (GET) or request body (POST). Collecting them in a String[]is the most straightforward choice as it is also used as-is in the Servlet API, so I really don't see any reason to collect it in a HashSetlike structure first, or do a Collections#shuffle()or whatever and then convert it to String[]afterwards.

所以,那部分是安全的。现在的 servletcontainer,在逻辑上是一个体面和高效的实现,它会在 HTTP 输入流进入时立即对其进行处理,因此参数将按照它们出现在请求 URI (GET) 或请求正文 (POST) 中的顺序进行处理。将它们收集在 a 中String[]是最直接的选择,因为它也在 Servlet API 中按原样使用,所以我真的看不出有任何理由HashSet先将它收集到类似的结构中,或者先执行 aCollections#shuffle()或其他操作,然后将其转换为String[]然后。

I can at least tell from experience, Tomcat does it the right way, so all major containers/appservers which are built on top of Tomcat/Catalina (IBM Websphere, JBoss AS, Sun Glassfish, etc) will also behave so. I only don't have hands on experience with Weblogic, but I would be surprised if it processes it differently (read: less efficiently).

我至少可以从经验中看出,Tomcat 以正确的方式执行此操作,因此构建在 Tomcat/Catalina 之上的所有主要容器/应用程序服务器(IBM Websphere、JBoss AS、Sun Glassfish 等)也将如此运行。我只是没有使用 Weblogic 的经验,但如果它以不同的方式处理它,我会感到惊讶(阅读:效率较低)。

Only the ordering of the parameter namesis not guaranteed, logically because it's backed by a HashMap.

仅不能保证参数名称的顺序,从逻辑上讲,因为它由HashMap.



Summarized: the parameters are collected in a HashMap<String, String[]>. The names are quaranteed not ordered due to the nature of the HashMap. The values (one parameter name can have multiple values, e.g. foo=bar1&foo=bar2&foo=bar3) are in turn however ordered due to the nature of String[], although this is not explicitly specified in the Servlet API.

总结:参数收集在一个HashMap<String, String[]>. 由于HashMap. 值(一个参数名称可以有多个值,例如foo=bar1&foo=bar2&foo=bar3)由于 的性质而依次排序String[],尽管这在 Servlet API 中没有明确指定。

To be on the safe side, you'd like to use a different approach, e.g.

为了安全起见,您想使用不同的方法,例如

foos=3&foo[0]=bar1&foo[1]=bar2&foo[2]=bar3

with

int foos = Integer.valueOf(request.getParameter("foos"));
for (int i = 0; i < foos; i++) {
    int foo = Integer.valueOf(request.getParameter("foo[" + i + "]"));
}

回答by giri

It depends on HttpServletRequest interface implementation.

它取决于 HttpServletRequest 接口的实现。

回答by yonran

Yes, the order of values returned by getParamterValues(String)and entries in getParameterMap()isguaranteed by the Servlet Specification. Here's the passage:

是的,值的顺序返回通过getParamterValues(String)并在条目getParameterMap()由Servlet规格保证。下面是这段话:

Data from the query string and the post body are aggregated into the request parameter set. Query string data is presented before post body data. For example, if a request is made with a query string of a=hello and a post body of a=goodbye&a=world, the resulting parameter set would be ordered a=(hello, goodbye, world).

来自查询字符串和帖子正文的数据聚合到请求参数集中。查询字符串数据在发布正文数据之前呈现。例如,如果使用 a=hello 的查询字符串和 a=goodbye&a=world 的帖子正文发出请求,则结果参数集将排序为 a=(hello, goodbye, world)。

(This is from the "HTTP Protocol Parameters" section within "The Request" chapter of the Servlet Specifications (SRV.4.1 in version 2.4, SRV.3.1 in version 2.5).)

(这是来自 Servlet 规范(2.4 版中的 SRV.4.1,2.5 版中的 SRV.3.1)“请求”一章中的“HTTP 协议参数”部分。)

There doesn'tappear to be a clean way to get the names in order (getParameterNames()does notreturn names in the order that the browser gave). I could, I suppose, parse the raw GET string from getQueryString()or parse the raw POST string from getInputStream(), but instead I think I will add another hidden parameter and then use getParameterValues(String)to get its order.

没有似乎是一个干净的方式来获得,以便(名称getParameterNames()没有在顺序返回名称,浏览器了)。我想,我可以从 解析原始 GET 字符串getQueryString()或从解析原始 POST 字符串getInputStream(),但我认为我将添加另一个隐藏参数,然后用于getParameterValues(String)获取其顺序。

If you're curious why I want to the parameters in order, it's because I have controls that the user can rearrange using jQuery, and I want to know the order that the user has chosen:

如果您好奇我为什么要按顺序排列参数,那是因为我拥有用户可以使用 jQuery 重新排列的控件,并且我想知道用户选择的顺序:

<form>
  <ul id=variables>
    <li>
      <input name=hello>hello
      <input type=hidden name=variableOrder value=hello>
    <li>
      <input name=world>world
      <input type=hidden name=variableOrder value=world>
  </ul>
</form>
<script src="jquery.js"></script>
<script src="jquery-ui.js"></script>
<script>
  jQuery('#variables').sortable().disableSelection();
</script>

回答by Bragnikita

I've got a problem to extract param-value map from HttpServletRequest in order in accordance with elements on the JSP. I wrote an OrderedRequestMap that parsers an application/x-www-form-urlencoded POST request body.

我在按照 JSP 上的元素按顺序从 HttpServletRequest 中提取参数值映射时遇到了问题。我编写了一个 OrderedRequestMap 来解析 application/x-www-form-urlencoded POST 请求正文。

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;


public class OrderedRequestMap extends LinkedHashMap<String,String[]> {

private final String encoding;

public OrderedRequestMap(InputStream httpBody, String encoding) throws IOException {
    this.encoding = encoding;
    fill(httpBody);
}

private void fill(InputStream is) throws IOException {
    final InputStreamReader reader = new InputStreamReader(is, "ASCII");
    int c;
    StringBuilder sb = new StringBuilder(1000);
    while ((c = reader.read()) != -1) {
        char ch = (char)c;
        if (ch == '&') {
            put(sb.toString());
            sb = new StringBuilder(1000);
        } else {
            sb.append(ch);
        }
    }
    put(sb.toString());
}

private void put(String parameter) throws UnsupportedEncodingException {
    String[] pair = parameter.split("=");
    if (pair.length == 0 )
        return;
    String key = URLDecoder.decode(pair[0], encoding);
    String val = EMPTY_STR;
    if (pair.length > 1)
        val = URLDecoder.decode(pair[1], encoding);
    String[] values = get(key);
    if (values == null)
        values = new String[]{val};
    else {
        values = Arrays.copyOf(values, values.length+1);
        values[values.length - 1] = val;
    }
    put(key, values);
}


private static final String EMPTY_STR = "";
}

And call it like this

并这样称呼它

new OrderedRequestMap(request.getInputStream(), request.getCharacterEncoding());

Hope, it helps.

希望能帮助到你。