繁体   English   中英

使用 Spring RestTemplate 时如何避免 [] 的双重编码?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM