HttpServletRequest.getParameterValues()
返回包含给定HTTP请求参数的所有值的String[]
。有没有人知道这个数组中的值的顺序是否由规范保证与请求中传递这些值的顺序相同?
例如,如果我有GET查询字符串x=1&x=2&x=3
,我是否保证在我致电String[] {"1", "2", "3"}
时收到getParameterValues()
?它似乎在实践中起作用,但我找不到任何指定必须如此的情况,所以我不愿意依赖它。
答案 0 :(得分:14)
ServletRequest(v2.5 javadoc)的javadoc没有提到有关该方法的值排序的任何信息。因此,我不会依赖于保留的顺序。
更新:还检查了2.5的spec文档,包含有关getParameterValues()的以下信息。它没有提到关于查询字符串的排序,所以我认为你看到的行为是实现细节,没有被定义为接口的一部分。
参数存储为一组 名称 - 值对。多参数 任何给定的值都可以存在 参数名称。以下方法 ServletRequest接口是 可用于访问参数:
在 getParameterValues方法返回一个 包含所有的String对象数组 与a关联的参数值 参数名称。返回的值 从getParameter方法必须是 String数组中的第一个值 返回的对象 getParameterValues。该 getParameterMap方法返回一个 java.util.Map的参数 请求,其中包含名称作为键 和参数值作为地图值。
为了将来参考,可以从Sun, I mean Oracle's website下载Java Servlet规范。您可以仔细检查您感兴趣的特定servlet版本。
答案 1 :(得分:11)
是的,Servlet规范保证getParamterValues(String)
返回的值的顺序和getParameterMap()
中的条目。这是段落:
查询字符串中的数据和 邮政机构聚合成了 请求参数集。请求参数 数据在帖子正文之前呈现 数据。例如,如果请求是 使用a = hello的查询字符串创建 和一个=再见& a =世界的帖子, 结果参数集将是 命令a =(你好,再见,世界)。
(这是来自Servlet规范的“请求”一章中的“HTTP协议参数”部分(版本2.4中的SRV.4.1,版本2.5中的SRV.3.1)。)
似乎不是一个干净的方式来按顺序获取名称(getParameterNames()
不按照浏览器给出的顺序返回名称)。我想,我可以从getQueryString()
解析原始GET字符串或解析来自getInputStream()
的原始POST字符串,但我想我会添加另一个隐藏参数然后使用getParameterValues(String)
来获取它的订单。
如果你好奇我为什么要按顺序参数,那是因为我有控件,用户可以使用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>
答案 2 :(得分:8)
它确实没有在Servlet规范中明确定义,但至少HTML表单规范在application/x-www-form-urlencoded部分明确定义它:
2.控件名称/值按照它们在文档中出现的顺序列出。
所以,那部分是安全的。现在servletcontainer,大多数逻辑上是一个体面和有效的实现将在它进入时立即处理HTTP输入流,因此参数将按照它们出现在请求URI(GET)或请求体(POST)中的顺序进行处理。在String[]
中收集它们是最直接的选择,因为它也在Servlet API中按原样使用,所以我真的没有理由先在HashSet
类似的结构中收集它,或者做一个Collections#shuffle()
或其他什么,然后将其转换为String[]
。
我至少可以从经验中看出,Tomcat是以正确的方式做到的,所以构建在Tomcat / Catalina(IBM Websphere,JBoss AS,Sun Glassfish等)之上的所有主要容器/应用程序服务器也会表现得如此。我只是没有掌握Weblogic的经验,但是如果它以不同的方式处理它会让我感到惊讶(阅读:效率较低)。
仅保证参数名称的顺序,逻辑上是因为它由HashMap
支持。
总结:参数收集在HashMap<String, String[]>
中。由于HashMap
的性质,保证名称不被命令。然而,由于foo=bar1&foo=bar2&foo=bar3
的性质,值(一个参数名称可以有多个值,例如String[]
)依次排序,尽管这在Servlet API中没有明确指定。
为了安全起见,你想使用不同的方法,例如
foos=3&foo[0]=bar1&foo[1]=bar2&foo[2]=bar3
与
int foos = Integer.valueOf(request.getParameter("foos"));
for (int i = 0; i < foos; i++) {
int foo = Integer.valueOf(request.getParameter("foo[" + i + "]"));
}
答案 3 :(得分:2)
我有一个问题,就是根据JSP上的元素按顺序从HttpServletRequest中提取param-value映射。我写了一个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 = "";
}
并像这样称呼它
new OrderedRequestMap(request.getInputStream(), request.getCharacterEncoding());
希望,这有帮助。
答案 4 :(得分:0)
这取决于HttpServletRequest接口的实现。