System.out.println(
new URI("http", "example.com", "/servlet", "a=x%20y", null));
结果是
http://example.com/servlet?a=x%2520y
,其中查询参数值与提供的不同。奇怪的是,这确实遵循了Javadoc的规定:“这些构造函数始终将百分比字符('%')引用。”
我们可以传递解码后的字符串
a=x y
,然后我们会得到一个合理的结果a=x%20y
。但是,如果查询参数值包含“&”字符怎么办?例如,如果该值本身是具有查询参数的URL,则会发生这种情况。看看这个(错误的)查询字符串:
a=b&c
。这里必须转义和号(a=b%26c
),否则这可能被视为查询参数a=b
和一些垃圾(c
)。如果我将其传递给URI构造函数,则会对其进行编码,并返回错误的URL:...?a=b%2526c
这个问题似乎使java.util.URI无用。我在这里错过了什么吗?答案摘要
java.net.URI确实知道URI的查询部分的存在,但它不理解查询部分的内部结构,这可能因每种方案而异。例如,java.net.URI不理解HTTP查询部分的内部结构。如果java.net.URI将查询视为不透明字符串并且不更改它,则这不会成为问题。但它尝试应用一些通用的百分比编码算法,这会破坏HTTP URL。
因此,尽管有构造函数,但我无法使用URI类可靠地组装URL的各个部分。我还要提到,从Java 7开始,相对路径操作的实现非常有限,仅在一个URL是另一个URL的前缀时才起作用。这两个功能(以及它们的更精简的接口)是我对java.net.URI感兴趣的原因,但它们都不适用于我。
最后,我使用java.net.URL进行解析,并编写了代码来从部分组装URL并使两个URL相对。我还检查了Apache HttpClient URIBuilder类,尽管它确实理解HTTP查询字符串的内部结构,但截至4.3,在处理整个查询部分时与java.net.URI一样存在编码问题。
a=b&c
在语法上是有效的,但它并不意味着显然想要的查询参数a
的值为b&c
。必须转义 "&" 符号,但 URI 在 toString() 中返回混乱的 URL。让我们看一个更现实的例子,在return
参数中传递相对 URLmypage?hello=world
。完整有效的 URL 是:http://example.com/some?return=mypage%3Fhello%3Dworld
。 我应该在 java.net.URI 多参数构造函数中传递什么来获得这个完整的 URL? - Hontvári LeventeURI
类进行任何特殊格式化。 - Sotirios Delimanolisa=x%20y
不是一个有效的查询字符串。请注意,RFC规定:“在正常情况下,仅在从其组成部分生成URI的过程中对URI中的八位组进行百分比编码”。因此,a=x%20y
变成了a=x%2520y
。 javadoc指出,除了一些小偏差外,java.net.URI
实例表示URI引用。 - Sotirios Delimanolis&
可以作为查询组件内的分隔符和数据字符。在后一种情况下,它必须进行百分号编码。因为 URI 不理解查询组件的内部结构,所以它无法确定 & 是分隔符还是数据字符。因此,正如您所写的那样,由用户即我的代码来决定。现在,如果我对不是分隔符而是数据字符的 & 进行百分号编码,则 URI.toString() 将返回错误的字符串。我仍然不知道应该传递什么参数给 URI 多参数构造函数才能获得我上面写的示例 URL。 - Hontvári Levente