我正在努力理解UriComponentsBuilder
的行为。我想用它来对查询参数中的网址进行编码,但它似乎只会转义%
个字符,而不会转义其他必要的字符,例如&
。
查询参数中未完全编码的URL示例:
UriComponentsBuilder.fromUri("http://example.com/endpoint")
.queryParam("query", "/path?foo=foo&bar=bar")
.build();
输出:http://example.com/endpoint?query=/path?foo=foo&bar=bar
这是不正确的,因为未编码的&
会导致bar=bar
被解释为/endpoint
的查询参数,而不是/path
。
但是,如果我使用包含%
字符::
UriComponentsBuilder.fromUri("http://example.com/endpoint")
.queryParam("query", "/path?foo=%20bar")
.build();
输出:http://example.com/endpoint?query=/path?foo=%2520bar
%
字符已转义。
UriComponentsBuilder
自动转义%
个字符而不是其他保留字符似乎不一致。
使用UriComponentsBuilder
将网址编码为查询参数的正确流程是什么?
答案 0 :(得分:4)
在您的示例中,构建UriComponents
对象未进行编码或规范化。为确保应用编码:
通过调用encode()
方法(也请参见normalize()
方法)自己编码:
UriComponents u = UriComponentsBuilder.fromHttpUrl("http://example.com/endpoint")
.queryParam("query", "/path?foo=foo&bar=bar")
.build()
.encode();
// http://example.com/endpoint?query=/path?foo%3Dfoo%26bar%3Dbar
如果用于构造build(true)
的参数已经编码,请使用UriComponents
方法
UriComponents u = UriComponentsBuilder.fromHttpUrl("http://example.com/endpoint")
.queryParam("query", "/path?foo=foo&bar=bar")
.build(true);
// IllegalArgumentException: Invalid character '=' for QUERY_PARAM in "/path?foo=foo&bar=bar"
在内部HierarchicalUriComponents.encode(String)
方法下执行实际的编码。在几次内部调用之后,它调用HierarchicalUriComponents.encodeBytes(byte[], HierarchicalUriComponents.Type)
,其中HierarchicalUriComponents.Type
枚举控制URL哪一部分中允许使用哪些字符。此检查基于RFC 3986。简而言之,Spring对URL的每个部分都有自己的编码逻辑。
答案 1 :(得分:3)
使用的语法不正确
使用UriComponentsBuilder.fromUri()
参数代替String
URI
。如果您要将URL作为String
传递,则将其用作:
UriComponentsBuilder
.fromUriString("http://example.com/endpoint")
.queryParam("query", URLEncoder.encode("/path?foo=%20bar","UTF-8"))
.build();
&
是有效的URL字符,因此不会被编码,但是%
并不是这个原因
被解码为%25
。
如果您想了解如何与RestTemplate
一起使用,请参考:RestTemplate.exchange() does not encode '+'?