java 避免使用 Spring 的 RestTemplate 对 URL 查询参数进行双重编码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34321361/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Avoid Double Encoding of URL query param with Spring's RestTemplate
提问by cscan
I'm trying to use Spring's RestTemplate::getForObject to make a request for a URL which has a URL query param.
我正在尝试使用 Spring 的 RestTemplate::getForObject 来请求具有 URL 查询参数的 URL。
I've tried:
我试过了:
- Using a string
- Creating a URI with URI::new
- Creating a URI with URI::create
- Using UriComponentsBuilder to build the URI
- 使用字符串
- 使用 URI::new 创建 URI
- 使用 URI::create 创建 URI
- 使用 UriComponentsBuilder 构建 URI
No matter which of these I use, encoding the url query param with URLEncoder::encode gets double encoded and using this encoding leaves the url query param unencoded.
无论我使用其中的哪一个,使用 URLEncoder::encode 对 url 查询参数进行编码都会得到双重编码,并且使用此编码会使 url 查询参数未编码。
How can I send this request without double encoding the URL? Here's the method:
如何在不对 URL 进行双重编码的情况下发送此请求?这是方法:
try {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(detectUrl)
.queryParam("url", URLEncoder.encode(url, "UTF-8"))
.queryParam("api_key", "KEY")
.queryParam("api_secret", "SECRET");
URI uri = builder.build().toUri();
JSONObject jsonObject = restTemplate.getForObject(uri, JSONObject.class);
return jsonObject.getJSONArray("face").length() > 0;
} catch (JSONException | UnsupportedEncodingException e) {
e.printStackTrace();
}
Here's an example:
下面是一个例子:
Without URLEncoder:
没有 URLEncoder:
http://www.example.com/query?url=http://query.param/example&api_key=KEY&api_secret=SECRET
With URLEncoder:
使用 URLEncoder:
http://www.example.com/query?url=http%253A%252F%252Fquery.param%252Fexample&api_key=KEY&api_secret=SECRET
':' should be encoded as %3A and '/' should be encoded as %2F. This does happen - but then the % is encoded as %25.
':' 应编码为 %3A,而 '/' 应编码为 %2F。这确实发生了 - 但随后 % 被编码为 %25。
回答by Sotirios Delimanolis
A UriComponentsBuilderis a builder for UriComponentswhich
AUriComponentsBuilder是一个建造者,UriComponents其中
Represents an immutable collection of URI components, mapping component type to
Stringvalues.
表示 URI 组件的不可变集合,将组件类型映射到
String值。
The URI specificationdefines what characters are allowed in a URI. This answersummarizes the list to the characters
该URI规范定义了什么角色被允许在一个URI。这个答案总结了字符列表
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
By those rules, your URI
根据这些规则,您的 URI
http://www.example.com/query?url=http://query.param/example&api_key=KEY&api_secret=SECRET
is perfectly valid and requires no additional encoding.
是完全有效的,不需要额外的编码。
The method URLEncoder#encode(String, String)
方法 URLEncoder#encode(String, String)
Translates a string into
application/x-www-form-urlencodedformat using a specific encoding scheme.
application/x-www-form-urlencoded使用特定的编码方案将字符串转换为格式。
That is not the same thing. That process is defined here, and URLEncoder(afaik) should be following it pretty closely.
那不是一回事。该过程在此处定义,并且URLEncoder(afaik)应该非常密切地遵循它。
In your original code, using URLEncoder#encodeconverted your input urlinto
在您的原始代码中,使用URLEncoder#encode将您的输入url转换为
http%3A%2F%2Fquery.param%2Fexample
The character %is invalid in a URI so must be encoded. That's what the UriComponentsobject constructed by your UriComponentsBuilderis doing.
该字符%在 URI 中无效,因此必须进行编码。这就是你UriComponents构造的对象UriComponentsBuilder正在做的事情。
This is unnecessary since your URI is completely valid to begin with. Get rid of the use of URLEncoder.
这是不必要的,因为您的 URI 一开始就完全有效。摆脱使用URLEncoder.

