1. Introduction

RestTemplate is an abstraction layer provided by Spring to invoke Restful services. It simplifies the way of communicating with Restful services and hides unnecessary details, allowing us to invoke Restful services more elegantly in applications. However, since Spring 5.0, RestTemplate is in maintenance mode, where no new features are developed and only routine maintenance is performed. Spring recommends that we use WebClient, another API that supports both synchronization, asynchrony, and Stream. But we don’t have a better option under Spring MVC right now.

2. Usage scenarios of the RestTemplate

We often use third-party Rest API services in our projects, such as SMS, delivery queries, weather forecasts, and so on. You can use the RestTemplate to call any of these third parties as long as they provide Rest apis.

3. Initialize the RestTemplate

RestTemplate is already integrated as long as your project uses Spring MVC. However, this class is not automatically injected into the Spring IoC container because many Rest apis are special and its build class RestTemplateBuilder is automatically injected into the Spring IoC container for more flexibility in customization. We can initialize it like this:

package cn.felord.rest.webclient;

import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/ * * *@author felord.cn
 * @since14:58 * * /
@Component
public class SomeWeb {

    private final RestTemplateBuilder restTemplateBuilder;

    public SomeWeb(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplateBuilder = restTemplateBuilder;
    }

    public RestTemplate restTemplate(a) {
        // Customize with Builder
        return restTemplateBuilder.requestFactory(OkHttp3ClientHttpRequestFactory::new). build(); }}Copy the code

Best practice: Try to customize the RestTemplate for each third-party service, and try not to share it unless the processes of these third-party services are exactly the same.

2.1 RestTemplate underlying

By default, the RestTemplate using java.net.HttpURLConnection as implementation, a use it but there is exception response status (for example, 401), will throw an exception, so we usually don’t use it. We can switch to the Netty, Apache HttpComponents, okHttp default client library, refer to 2 requestFactory(ClientHttpRequestFactory Factory) access method, You can also implement ClientHttpRequestFactory to connect to other third-party libraries. I’m using okHttp here. You can customize these third-party libraries to provide features to enrich your RestTemplate, such as setting request timeouts.

3. Examples of common methods

RestTemplate supports all Restful style methods, and you can choose as you like, but we’ll cover only a few common ones here. All methods support URI templates and URI parameters, which can be written as follows:

# Similar to @pathVariable in Spring MVC
https://api.apiopen.top/{method}
Copy the code

{3.1 get | post} ForEntity

After getting the request, the response is mapped as the ResponseEntity

response object, a wrapper object for the response body. We used the following code to randomly request 5 photos of beautiful little sisters that you can print to view:

    @Autowired
    RestTemplate restTemplate;

    void contextLoads(a) {
        String url = "https://api.apiopen.top/getImages? page=0&count=5";
        ResponseEntity<String> responseEntity = restTemplate
                .getForEntity(url,String.class);
        String body = responseEntity.getBody();
        System.out.println("body = " + body);
    }
Copy the code

Change the above method to the sequential variable arguments:

        String url = "https://api.apiopen.top/getImages? page={page}&count={count}";
        ResponseEntity<String> responseEntity = restTemplate
                .getForEntity(url,String.class,0.5);
        String body = responseEntity.getBody();
        System.out.println("body = " + body);
Copy the code

Or use Map

:
,object>

        String url = "https://api.apiopen.top/getImages? page={page}&count={count}";
        HashMap<String, Object> uriParams = new HashMap<>();
        uriParams.put("page".0);
        uriParams.put("count".5);
        ResponseEntity<String> responseEntity = restTemplate
                .getForEntity(url, String.class, uriParams);
        String body = responseEntity.getBody();
        System.out.println("body = " + body);
Copy the code

The POST request passes in an additional VO object, possibly null, or MultiValueMap to carry the request body parameters, which are eventually packed

Org. Springframework. HTTP HttpEntity object, the object can contain the following two parts:

  • Request body object, you can use entity VO,MultiValueMap
  • Request header object,org.springframework.http.HttpHeaders
 String url = "https://api.apiopen.top/getImages? page={page}&count={count}";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<UserVO> httpEntity = new HttpEntity<>(new UserVO("userName"), headers);
        HashMap<String, Object> uriParams = new HashMap<>();
        uriParams.put("page".0);
        uriParams.put("count".5);
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, httpEntity, String.class, uriParams);
Copy the code

The above is an example of invoking a Post request with a request body and a request header.

{3.2 get | post} ForObject

We can also map the response directly to a POJO. Of course, you need to be familiar with the structure of the response result. It is recommended to map to a String first to see the structure. We give an example and refer to 3.1 for other examples:

        String url = "https://api.apiopen.top/getImages? page={page}&count={count}";
        HashMap<String, Object> uriParams = new HashMap<>();
        uriParams.put("page".0);
        uriParams.put("count".5);
        String forObject = restTemplate.getForObject(url, String.class, uriParams);
        System.out.println("forObject = " + forObject);
Copy the code

3.3 headForHeaders

This method is used to get the headers of all URI template declaration resources

        String url = "https://api.apiopen.top/getImages? page={page}&count={count}";
        HashMap<String, Object> uriParams = new HashMap<>();
        uriParams.put("page".0);
        uriParams.put("count".5);
        HttpHeaders httpHeaders = restTemplate.headForHeaders(url, uriParams);
        System.out.println(httpHeaders);
Copy the code

The result is:

[Access-Control-Allow-Headers:"Content-Type, x-requested-with, X-Custom-Header, Authorization", Access-Control-Allow-Methods:"POST, GET, OPTIONS, DELETE", Access-Control-Allow-Origin:"*", Access-Control-Max-Age:"3600", Cache-Control:"private", Content-Length:"608", Content-Type:"application/json; charset=UTF-8", Date:"Tue, 14 Apr 2020 15:25:19 GMT", Expires:"Thu, 01 Jan 1970 00:00:00 GMT"]
Copy the code

3.4 postForLocation

Instead of returning the full resource, this Post operation returns the newly created resource URI. For example, uploading a file returns a request path for a resource.

3.5 put/delete

Corresponding to put and DELETE requests, refer to the previous API.

3.6 optionsForAllow

This method gets one or more of the request methods allowed by the URI, such as GET, POST, PUT, and DELETE.

3.7 exchange

This method is a universal request method, supporting GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE. If the above method does not meet the requirements, you can use this method to customize, this method provides a more flexible API. For example, you can customize the headers of GET methods to put Jwt tokens in them, which is something that getForObject can’t compare to.

4. To summarize

RestTemplate is a useful request coordinator that shields the complexity of invoking services without sacrificing flexibility. But it’s worth noting that it’s on its way out. Even the best programmers have to change careers, right?

Follow our public id: Felordcn for more information

Personal blog: https://felord.cn