RestTemplate.exchange() does not encode '+'

2019-06-12 10:33发布

The RestTemplate.exchange() will encode all the invalid characters in URL but not + as + is a valid URL character. But how to pass a + in any URL's query parameter?

1条回答
女痞
2楼-- · 2019-06-12 11:18

If the URI you pass to the RestTemplate has encoded set as true then it will not perform the encoding on the URI you pass else it will do.

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.util.Collections;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

class Scratch {

  public static void main(String[] args) {

    RestTemplate rest = new RestTemplate(
        new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));

    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-Type", "application/json");
    headers.add("Accept", "application/json");
    HttpEntity<String> requestEntity = new HttpEntity<>(headers);

    UriComponentsBuilder builder = null;
    try {
      builder = UriComponentsBuilder.fromUriString("http://example.com/endpoint")
          .queryParam("param1", URLEncoder.encode("abc+123=", "UTF-8"));
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }

    URI uri = builder.build(true).toUri();
    ResponseEntity responseEntity = rest.exchange(uri, HttpMethod.GET, requestEntity, String.class);
  }

}

So if you need to pass a query param with + in it then the RestTemplate will not encode the + but every other invalid URL character as + is a valid URL character. Hence you have to first encode the param (URLEncoder.encode("abc+123=", "UTF-8")) and then pass the encoded param to RestTemplate stating that the URI is already encoded using builder.build(true).toUri();, where true tells the RestTemplate that the URI is alrady encoded so not to encode again and hence the + will be passed as %2B.

  1. With builder.build(true).toUri(); OUTPUT : http://example.com/endpoint?param1=abc%2B123%3D as the encoding will be perfromed once.
  2. With builder.build().toUri(); OUTPUT : http://example.com/endpoint?param1=abc%252B123%253D as the encoding will be perfromed twice.
查看更多
登录 后发表回答