Use RestTemplate to make third-party Rest service calls

1 Introduction

RestTemplateIt is an abstraction layer that calls Restful services provided by Spring . It simplifies the communication with Restful services, hides unnecessary details, and allows us to call Restful services more elegantly in applications . However, it is in maintenance mode after Spring 5.0 , no longer develop new features, only some routine maintenance. Spring recommends that we use another API that supports synchronous, asynchronous and Stream at the same time - WebClient . But under Spring MVC we currently have no better choice.RestTemplate

2. RestTemplate usage scenarios

We often use third-party Rest API services in projects , such as SMS, express query, weather forecast, etc. These third parties as long as the Rest Api , you can use RestTemplateto call them.

3. Initialize RestTemplate

As long as your project uses Spring MVC, it is already integrated RestTemplate. But this kind usually are not automatically injected into the Spring IoC container, because a lot of Rest API has a special, more flexible to customize its construction class RestTemplateBuilderis automatically injected into the Spring IoC container. 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
 * @since 14:58
 **/
@Component
public class SomeWeb {

    private final RestTemplateBuilder restTemplateBuilder;

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

    public RestTemplate restTemplate() {
        // 通过 builder 定制
        return restTemplateBuilder.requestFactory(OkHttp3ClientHttpRequestFactory::new).
                build();
    }
}
复制代码

Best practice: customize each third-party service as much as possible RestTemplate, and try not to use it publicly, unless these third-party processes are completely consistent.

2.1 RestTemplate bottom layer

By default, RestTemplateuse java.net.HttpURLConnectionas an implementation, but a response to abnormal state (such as 401) when it is used, an exception is thrown, so we are not using it. We can switch to Netty , the Apache HttpComponents , okHttp client library default implementation, reference 2 the requestFactory(ClientHttpRequestFactory factory)access method can be realized on their own ClientHttpRequestFactorydocking access other third-party libraries. Here I use okHttp . You can customize the features provided by these third-party libraries to enrich yours RestTemplate, such as setting the request timeout.

3. Examples of common method scenarios

RestTemplateSupport all Restful style methods, you can choose according to your needs, here we only introduce some common methods. All methods support URI templates and URI parameters, and support the following writing:

# 类似 spring mvc 中的 @PathVariable
https://api.apiopen.top/{method}
复制代码

3.1 {get|post}ForEntity

Get request will be mapped to a response ResponseEntity<T>in response to the object, a wrapper object body response. We use the following code to randomly request 5 pictures of a pretty lady, you can print to view:

    @Autowired
    RestTemplate restTemplate;

    void contextLoads() {
        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);
    }
复制代码

The above method is changed to variable parameters in order:

        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);
复制代码

Or use Map<String,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);
复制代码

post request additional will pass a possibly nullVO object, or MultiValueMapto carry the request body parameters, which will eventually be enclosed in

org.springframework.http.HttpEntity Object, the object can contain the following two parts:

  • Request body object, 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);
复制代码

The above is an example of calling a Post request and carrying the request body and request header.

3.2 {get|post}ForObject

We can also respond directly mapped to POJO , of course, you need to respond to the results of the structure is well aware, it is recommended to map to Stringcheck the structure. We give an example, other examples refer to 3.1 :

        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);
复制代码

3.3 headForHeaders

This method is used to obtain the header 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);
复制代码

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"]
复制代码

3.4 postForLocation

This Post operation does not return the complete resource, but returns the newly created resource URI. For example, uploading a file returns the request path of the resource.

3.5 put/delete

For put requests and delete requests, refer to the previous api.

3.6 optionsForAllow

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

3.7 exchange

This method is a general request method, which supports GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE . When the above method does not satisfy you, you can use this method to customize. This method provides a more flexible API. For example, you can It is incomparable to customize the request header of the GET method and put it into operations such as Jwt TokengetForObject .

4. Summary

RestTemplateIt is a very useful request coordinator, shielding the complexity of calling services without losing flexibility. But it is worth noting that it is withdrawing from the stage of history. Isn't there a day when awesome programmers also change careers?

关注公众号:Felordcn获取更多资讯

Personal blog: https://felord.cn

Guess you like

Origin juejin.im/post/5e9933e5e51d45471263f714