Java EE有ServletRequest.getParameterValues() .
在非EE平台上,URL.getQuery()只返回一个字符串 .
在Java EE上正确解析URL中的查询字符串的常用方法是什么?
< rant >
在尝试制作自己的解析器的答案中很受欢迎 . 这是非常有趣和令人兴奋的微编码项目,但 I cannot say that it is a good idea :(
下面的代码片段通常有缺陷或破损,顺便说一下 . 打破它们对读者来说是一个有趣的练习 . 并且黑客攻击使用它们的网站 .
解析查询字符串是一个定义明确的问题,但阅读规范和理解细微差别并非易事 . 让一些平台库编码器做出艰苦的工作,并为您做好修复,这要好得多!
< /rant >
24 回答
在Android上,Apache库提供了一个Query解析器:
http://developer.android.com/reference/org/apache/http/client/utils/URLEncodedUtils.html和http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/utils/URLEncodedUtils.html
使用Apache HttpComponents并将其与某些集合代码连接起来以按值访问params:http://www.joelgerard.com/2012/09/14/parsing-query-strings-in-java-and-accessing-values-by-key/
因为Android M的东西变得更加复杂 . android.net.URI .getQueryParameter()的答案有一个在JellyBean之前打破空格的错误 . Apache URLEncodedUtils.parse()工作,但是deprecated in L和removed in M .
所以现在最好的答案是UrlQuerySanitizer . 这已经存在于API级别1并且仍然存在 . 它还会让您考虑棘手的问题,例如如何处理特殊字符或重复值 .
最简单的代码是
在Android上:
这是BalusC's answer,但它编译并返回结果:
如果你的类路径上有jetty(服务器或客户端)库,你可以使用jetty util类(参见javadoc),例如:
如果你使用的是Spring 3.1或更高版本(yikes,希望支持能够进一步发展),你可以使用
UriComponents
和UriComponentsBuilder
:components.getQueryParams()
返回MultiValueMap<String, String>
Here's some more documentation .
对于servlet或JSP页面,您可以使用request.getParameter(“paramname”)获取查询字符串键/值对
还有其他方法可以做到,但这就是我在我创建的所有servlet和jsp页面中的方式 .
解析查询字符串比看起来要复杂一些,具体取决于你想要的宽容程度 .
首先,查询字符串是ascii字节 . 您可以一次读取这些字节并将它们转换为字符 . 如果角色是?或者然后它表示参数名称的开始 . 如果字符是=则它表示参数值的开始 . 如果字符是%,则它表示编码字节的开始 . 这是它变得棘手的地方 .
当您读入%char时,您必须读取接下来的两个字节并将它们解释为十六进制数字 . 这意味着接下来的两个字节将是0-9,a-f或A-F . 将这两个十六进制数字粘在一起以获取字节值 . 但请记住, bytes are not characters . 您必须知道用于编码字符的编码 . 字符é在UTF-8中的编码与ISO-8859-1中的编码相同 . 一般来说,这是肯定的 . 一些用户代理会告诉您请求中的字符编码;如果您有完整的HTTP请求,可以尝试阅读 . 如果你只是孤立的网址,祝你好运 .
无论如何,假设您正在使用UTF-8或其他一些多字节字符编码,现在您已经解码了一个编码字节,您必须将它放在一边,直到您捕获下一个字节 . 您需要所有编码的字节在一起,因为您不能一次正确地解码一个字节 . 将所有字节放在一起,然后一次解码它们以重建你的角色 .
此外,如果您想要宽容并且考虑到破坏网址的用户代理,它会变得更有趣 . 例如,一些Webmail客户端对事物进行了双重编码 . 或者加倍?&=字符(例如:
http://yoursite.com/blah??p1==v1&&p2==v2
) . 如果您想尝试优雅地处理此问题,则需要向解析器添加更多逻辑 .仅供参考,这是我最终得到的(基于URLEncodedUtils,并返回Map) .
特征:
它接受url的查询字符串部分(你可以使用
request.getQueryString()
)一个空的查询字符串将产生一个空的
Map
没有值的参数(?test)将映射为空
List<String>
码:
兼容性帮助程序(值存储在String数组中,就像ServletRequest.getParameterMap()中一样):
在Android上,我尝试使用@diyism回答,但我遇到了@rpetrich引发的空格字符问题,例如:我填写一个表单,其中
username = "us+us"
和password = "pw pw"
导致URL字符串看起来像:但是,@ diyism代码返回
"us+us"
和"pw+pw"
,即它不检测空格字符 . 如果使用%20
重写URL,则会识别空格字符:这导致以下修复:
使用 Guava :
我有方法来实现这个目标:
1) :
2) and the easiest way to do this Using Uri class:
这是如何使用两种方法之一的示例:
tagValue的值是
800
在Android上,您可以使用android.net.Uri类的Uri.parse静态方法来完成繁重的工作 . 如果你想要反正使用它 .
这对我有用..我不确定为什么每个人都在一个 Map 之后,List>我需要的只是一个简单的名称值Map .
为了简单起见,我使用了URI.getQuery();
在Android上它的简单如下代码:
此外,如果您不想注册每个预期的查询键,请使用:
致电之前:
Guava的Multimap更适合这种情况 . 这是一个简短的干净版本:
Apache AXIS2具有QueryStringParser.java的自包含实现 . 如果您不使用Axis2,只需从此处下载源代码和测试用例 -
http://svn.apache.org/repos/asf/axis/axis2/java/core/trunk/modules/kernel/src/org/apache/axis2/transport/http/util/QueryStringParser.java
http://svn.apache.org/repos/asf/axis/axis2/java/core/trunk/modules/kernel/test/org/apache/axis2/transport/http/util/QueryStringParserTest.java
我不认为JRE中有一个 . 您可以在Apache HttpClient等其他软件包中找到类似的功能 . 如果您不使用任何其他包,您只需编写自己的包 . 这并不难 . 这是我用的,
根据BalusC的答案,我写了一些示例-Java-Code:
在这里回答是因为这是一个受欢迎的主题 . 这是Kotlin中使用推荐的
UrlQuerySanitizer
api的干净解决方案 . See the official documentation . 我添加了一个字符串生成器来连接并显示参数 .此方法采用uri并返回par name和par值的映射
你说“Java”,但“不是Java EE” . 您是说您使用的是JSP和/或servlet而不是完整的Java EE堆栈?如果是这种情况,那么您仍然可以使用request.getParameter() .
如果你的意思是你正在编写Java,但是你没有编写JSP或servlet,或者你只是使用Java作为参考点,但是你在其他没有内置参数解析的平台上......哇,这听起来像是一个不太可能的问题,但如果是这样,原则是:
(我可以编写Java代码,但这样做毫无意义,因为如果你有Java可用,你可以使用request.getParameters . )