HttpServletRequest-获取查询字符串参数,无表单数据


76

HttpServletRequest中getParameterMap返回所有查询字符串参数和post数据参数的Map。

有没有办法获取仅查询字符串参数的映射?我试图避免使用getQueryString并解析出值。


15
您可以同时拥有两个...您可以在POST请求中拥有查询字符串参数。在这种情况下,它们全都由“ getParameterMap”返回
JasonStoltz 2011年

哦好的。为什么一个人都需要,只是好奇?
雅各布

2
因为在结果页面上,我希望查询字符串出现在url中/出现在查询字符串中。我们有一个跟踪系统,该系统在查询字符串中查找特定的参数。
JasonStoltz 2011年

req.getParameterMap()。containsKey(“ username”);
Parag Jadhav

Answers:


22

与cularis所说的相反,参数图中可能同时存在两者。

我认为最好的方法是代理parameterMap并为每个参数检索检查queryString是否包含“&?<parameterName> =”。

请注意,如Qerub所指出的,在进行此检查之前,必须对parameterName进行URL编码。

这样可以节省您的分析,但仍然只提供URL参数。


2
请注意,parameterName必须先对网址进行编码,然后才能进行此检查。
qerub

12
查询字符串从不包含?。那是URI和查询字符串之间的分隔符。
BalusC 2013年

嗨,@ DoubleMalt,我有相同的要求,但无法获得您提供的解决方案。您可以提供示例代码吗?
Vishal Zanzrukia 2014年

@VishalZanzrukia:您的无效代码是什么?
DoubleMalt 2014年

1
我喜欢这个主意,但查询字串中并不总是有“ =”字元。如果参数值为空,则查询字符串中仅<parameterName>。我个人认为用“&”和“ =”分隔将是更好的解决方案。
布伦(Bren)

95

您可以使用request.getQueryString(),如果查询字符串是像

username=james&password=pwd

要获得名称,您可以执行此操作

request.getParameter("username"); 

适用于Java Server页面。
Jorgesys '16

2
第二个将破坏请求流,我假设问题是如何获取用户名并保持输入流以供以后处理
Pavel Niedoba

23

Servlet API缺少此功能,因为它是在许多人认为查询字符串和消息正文只是发送参数的两种不同方式时创建的,而不是意识到参数的用途根本不同。

查询字符串参数?foo = bar是URL的一部分,因为它们涉及标识资源(可能是许多资源的集合),例如“所有42岁的人”:

GET /人?年龄= 42

POST或PUT中的消息正文参数在那里表示对目标资源的修改。Fx为属性“ hair”设置值:

PUT /人?年龄= 42

头发=灰色

因此,绝对可以同时使用查询参数和主体参数,并将它们分开使用,以实现不同的用途,这是RESTful的。Java Servlet API中肯定缺少该功能。


12

正如其他答案所述,无法使用servlet API获取查询字符串参数。

因此,我认为获取查询参数的最佳方法是自己解析查询字符串。(遍历参数并检查查询字符串是否包含参数更为复杂)

我写了下面的代码来获取查询字符串参数。使用也支持CSV分隔查询参数值的Apache StringUtils和ArrayUtils。

示例:username=james&username=smith&password=pwd1,pwd2将返回

password : [pwd1, pwd2] (长度= 2)

username : [james, smith] (长度= 2)

public static Map<String, String[]> getQueryParameters(HttpServletRequest request) throws UnsupportedEncodingException {
    Map<String, String[]> queryParameters = new HashMap<>();
    String queryString = request.getQueryString();
    if (StringUtils.isNotEmpty(queryString)) {
        queryString = URLDecoder.decode(queryString, StandardCharsets.UTF_8.toString());
        String[] parameters = queryString.split("&");
        for (String parameter : parameters) {
            String[] keyValuePair = parameter.split("=");
            String[] values = queryParameters.get(keyValuePair[0]);
            //length is one if no value is available.
            values = keyValuePair.length == 1 ? ArrayUtils.add(values, "") :
                    ArrayUtils.addAll(values, keyValuePair[1].split(",")); //handles CSV separated query param values.
            queryParameters.put(keyValuePair[0], values);
        }
    }
    return queryParameters;
}

我认为这比接受的答案要好得多,不知道为什么要避免解析查询字符串,因为创建代理不是更好的解决方案
Pavel Niedoba 17/02/12

1
我只是想知道,如果任何查询参数&的值中都包含字符,它是否会为您提供正确的结果
amdg

1
@amdg-该字符将进行URL编码,因此代码是好的。如果未编码,则字符串将不可解析。
马拉松赛

考虑同时使用URLDecoder.decode(keyValuePair[0])(或[1]):docs.oracle.com/javase/6/docs/api/java/net/URLDecoder.html
冥王星

1
此处不考虑具有csv分隔值的查询参数。例如:username=james&username=smith&password=pwd1,pwd2将有一个包含2个用户名值(正确)但只有1个密码值(不正确)的地图
Niv

3

Java 8

return Collections.list(httpServletRequest.getParameterNames())
                  .stream()
                  .collect(Collectors.toMap(parameterName -> parameterName, httpServletRequest::getParameterValues));

2

恐怕没有办法将查询字符串参数与post参数分开解析。顺便说一句,缺少此类API可能意味着您应该检查设计。为什么在发送POST时使用查询字符串?如果您确实想将更多数据发送到URL,请使用类似REST的约定,例如,而不是发送

http://mycompany.com/myapp/myservlet?first=11&second=22

说:

http://mycompany.com/myapp/myservlet/11/22


我在POST中使用查询字符串参数,因为我想维护通过POST传递给原始表单的所有查询字符串。这主要是为了跟踪目的...我不确定在这种情况下是否可以使用类似REST的约定,因为我非常确定跟踪库会在查询字符串中查找特定的参数。
JasonStoltz 2011年

有什么特别的理由建议您将类似REST的约定用于查询字符串参数?不知道我的优势是什么?
2011年

8
“顺便说一句,缺少此类API可能意味着您应该检查设计。” 在这种情况下,这意味着Oracle应该检查其设计:)
Stijn de Witt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.