我正在尝试使用Spring的RestTemplate :: getForObject来请求具有URL查询参数的URL.
我试过了:
使用字符串
使用URI :: new创建URI
使用URI :: create创建URI
使用UriComponentsBuilder构建URI
无论我使用哪一个,使用URLEncoder :: encode对url查询参数进行编码都会进行双重编码,并且使用此编码会使url查询参数无法编码.
如何在不对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(); }
这是一个例子:
没有URLEncoder:
http://www.example.com/query?url=http://query.param/example&api_key=KEY&api_secret=SECRET
使用URLEncoder:
http://www.example.com/query?url=http%253A%252F%252Fquery.param%252Fexample&api_key=KEY&api_secret=SECRET
':'应编码为%3A,'/'应编码为%2F.这确实发生了 - 但是%编码为%25.
一个UriComponentsBuilder
是一个建设者UriComponents
,其
表示URI组件的不可变集合,将组件类型映射到
String
值.
该URI规范定义了允许在URI什么字符.这个答案总结了人物的清单
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
根据这些规则,你的URI
http://www.example.com/query?url=http://query.param/example&api_key=KEY&api_secret=SECRET
完全有效,无需额外编码.
方法 URLEncoder#encode(String, String)
application/x-www-form-urlencoded
使用特定编码方案将字符串转换为格式.
那不是一回事.这个过程在这里定义,URLEncoder
(afaik)应该非常密切地关注它.
在原始代码中,使用URLEncoder#encode
将输入url
转换为
http%3A%2F%2Fquery.param%2Fexample
该字符%
在URI中无效,因此必须进行编码.这就是你UriComponents
构建的对象UriComponentsBuilder
正在做的事情.
这是不必要的,因为您的URI完全有效.摆脱使用URLEncoder
.