[英]How to avoid double-encoding of [] when using Spring RestTemplate?
我有一个调用此 REST 端点的 Spring Boot 2.2.5 应用程序
@RequestMapping(path = "/usable/search")
public List<Provider> findUsable(
@RequestParam(name = "country-id", required = false) Integer countryId,
@RequestParam(name = "network-ids[]", required = false) List<Integer> networkIds,
@RequestParam(name = "usages[]") Set<Usage> usages)
我的来电者确实
val url = clientUri.toString() + configuration.getUrl().getUseableProvidersForNetworks(); % 'providers/usable/search?'
val builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("usages[]", USAGES)
.queryParam("network-ids[]", networkIds);
val response =
restTemplate.exchange(
builder.toUriString(),
HttpMethod.GET,
entity,
new ParameterizedTypeReference<List<Provider>>() {});
其中USAGES
是一个Set<Usage>
并且networkIds
是一个List<Integer>
。
RestTemplate 由
RestTemplate eurekaRestTemplate() {
val requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setReadTimeout(TIMEOUT);
requestFactory.setConnectTimeout(TIMEOUT);
return new RestTemplate(new BufferingClientHttpRequestFactory(requestFactory));
}
问题: []
被双重编码为%255B%255D
并且我最终调用
providers/usable/search?usages%255B%255D=MESSAGE_DELIVERY&network-ids%255B%255D=2145118475&network-ids%255B%255D=-1536358371
这显然是行不通的; 服务器错过了如usages[]
。 它适用于 curl 与[]
而不是%255B%255D
。
我怎样才能避免这种情况?
解决方案是调用UriComponentsBuilder.build(false)
来指示UriComponentsBuilder
不要对 url 进行编码:
val response = restTemplate.exchange(
builder.build(false).toUriString(),
HttpMethod.GET,
entity,
new ParameterizedTypeReference<List<Provider>>() {});
这很棘手,因为使用 Mockito/JUnit 进行的测试会告诉您 url未编码,而使用MockRestServiceServer
的测试将显示一级编码( []
变为%5B%5D
)。
我认为你不应该使用 [] 来处理。 我的意思是,没有必要使用“[]”来命名你的参数。 为什么要这么做?
val builder = UriComponentsBuilder.fromHttpUrl(url)
.queryParam("usages", USAGES)
.queryParam("network-ids", networkIds);
将完美地适用于:
public List<Provider> findUsable(
@RequestParam(name = "country-id", required = false) Integer countryId,
@RequestParam(name = "network-ids", required = false) List<Integer> networkIds,
@RequestParam(name = "usages") Set<Usage> usages)
希望能帮助到你!
提示:在 URL 上使用数组/集合参数时要小心,您必须考虑 URL 长度限制
如果您希望将编码的 url 直接传递给RestTemplate
,您可以通过传递java.net.URI
而不是 String 来指示RestTemplate
不对 url 进行编码。 这是一个使用org.springframework.web.util.UriComponents
的示例
String url = "https://someurl/this%2Fis%2Fencoded/";
UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(url).build(true);
ResponseEntity<String[]> file = template.exchange(uriComponents.toUri(),
HttpMethod.GET, entity,String[].class);
通过传递UriComponentsBuilder.fromHttpUrl(url).build(true)
您实际上是在让UriComponents
知道您的 url 已经编码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.