First, background

The RestTemplate is used in the project to make requests to third-party interfaces. When you use get to query an interface, parameters need to be concatenated to the URL. Javabeans are not supported for parameter transmission, which is unfriendly to code.

Develop common writing methods

If it is a Get request, you would normally write:

If you do not use placeholders, the server will not receive arguments.

The server interface is defined as follows. The request result is that the parameter resolution fails and 400 error codes are returned

Third, expand practice

At this point, I thought, can we directly pass map, or a JavaBean to achieve the parameters? Looking at the source code, you see that RestTemplate has extension points that you can extend, and you’re on your way. RestTemplate has an interface that handles requests for urls,

public interface UriTemplateHandler {

// This method is the parameter map we passed in

URI expand(String uriTemplate, Map
       
         uriVariables)
       ,>;

URI expand(String uriTemplate, Object... uriVariables);

}
Copy the code

You can then define a custom UriTemplateHandler to handle the requested URL.

The code is as follows:

public class GetUriTemplateHandler implements UriTemplateHandler {

private UriTemplateHandler uriTemplateHandler = new DefaultUriBuilderFactory();

@Override

public URI expand(String uriTemplate, Map
       
         uriVariables)
       ,> {

// Use UriComponentsBuilder to append the request parameters to the URL. GetParamMultiValueMap is a custom map

uriTemplate = UriComponentsBuilder

.fromHttpUrl(uriTemplate)

.queryParams(new GetParamMultiValueMap(uriVariables)).toUriString();

log.info("Processed URL ==> {}", uriTemplate);

return uriTemplateHandler.expand(uriTemplate, uriVariables);

}

@Override

public URI expand(String uriTemplate, Object... uriVariables) {

returnuriTemplateHandler.expand(uriTemplate, uriVariables); }}Copy the code

GetParamMultiValueMap is implemented as follows:

public class GetParamMultiValueMap<K.V> implements MultiValueMap<K.V> {

private final Map<K, List<V>> map;

public GetParamMultiValueMap(Map<K, V> paramMap) {

Assert.notNull(paramMap, "'map' must not be null");

// Convert the request parameters to MultiValueMap

this.map = new HashMap<>();

paramMap.forEach((k, v) -> {

if (v instanceof List) {

map.put(k, (List<V>) v);

} else{ map.put(k, Lists.newArrayList(v)); }}); }}Copy the code

Once GetUriTemplateHandler is implemented, you simply replace the default UriTemplateHandler after the RestTemplate instantiation to use your own implementation

@Configuration

public class RestTemplateConfig {

@ConditionalOnClass(value = RestTemplate.class)

@Bean

public RestTemplate restTemplate(a) {

RestTemplate restTemplate = new RestTemplate();

// Replace the HTTP request component of the default JDK with okhttp3

restTemplate.setRequestFactory(new OkHttp3ClientHttpRequestFactory());

// Use custom URI handlers to append parameters to urls

restTemplate.setUriTemplateHandler(new GetUriTemplateHandler());

returnrestTemplate; }}Copy the code

Here are the results:

A correct return was received from the server.

Fourth, expand again

It is still a map that is passed. Can you pass a JavaBean directly?

The answer is yes, by wrapping the RestTemplate,

Convert Javabeans to Maps with the apache-Commont package

Inject into the Spring container

@Bean

public RestTemplateWrapper restTemplateWrapper(RestTemplate restTemplate) {

return new RestTemplateWrapper(restTemplate);

}
Copy the code

Tests using beans can be used to successfully pass parameters.

Received the service response successfully

ok receive message ===> test

The RestTemplate extension is used to extend the parameters of a Get request.