RestTemplate的一些坑和改造点 一、RestTemplate怎么引入和使用 二、给RestTemplate设置全局Header 三、对RestTemplate进行错误处理 四、给RestTemplate的Get设置RequestBody参数

在pom.xml文件中加入如下dependency:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

在项目的config文件夹下创建InitBeanConfig.java,添加如下代码:

1 @Bean
2 public RestTemplate getRestTemplate() {
3        return new RestTemplate();
4 }

使用的方式很简单,如下:

1 @Autowired
2 private RestTemplate restTemplate;

二、给RestTemplate设置全局Header

在config文件夹下创建HeaderRequestInterceptor.java

 1 import org.springframework.http.HttpRequest;
 2 import org.springframework.http.MediaType;
 3 import org.springframework.http.client.ClientHttpRequestExecution;
 4 import org.springframework.http.client.ClientHttpRequestInterceptor;
 5 import org.springframework.http.client.ClientHttpResponse;
 6 
 7 import java.io.IOException;
 8 
 9 /**
10  * @author 远猷
11  * @version 1.0.0
12  * @copyright xxx.com
13  * @description RestTemplate拦截器统一添加请求头
14  * @create 2021-04-29 17:40:34
15  */
16 public class HeaderRequestInterceptor implements ClientHttpRequestInterceptor {
17     @Override
18     public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
19         httpRequest.getHeaders().setContentType(MediaType.APPLICATION_JSON);
20         httpRequest.getHeaders().set("Http-Rpc-Type", "JsonContent");
21         httpRequest.getHeaders().set("Http-Rpc-Timeout", "3000");
22         httpRequest.getHeaders().set("app-name", "xxxx");
23         return clientHttpRequestExecution.execute(httpRequest, bytes);
24     }
25 }

在InitBeanConfig的代码中加入

1 @Bean
2 public RestTemplate getRestTemplate() {
3   RestTemplate restTemplate = new RestTemplate();
4   //给所有的Http请求加上请求头
5   restTemplate.setInterceptors(Collections.singletonList(new HeaderRequestInterceptor()));
6   return restTemplate;
7 }

三、对RestTemplate进行错误处理

在config文件夹下创建RestTemplateErrorHandler.java

 1 import org.springframework.http.client.ClientHttpResponse;
 2 import org.springframework.stereotype.Component;
 3 import org.springframework.web.client.ResponseErrorHandler;
 4 
 5 import java.io.IOException;
 6 
 7 /**
 8  * @author 远猷
 9  * @version 1.0.0
10  * @copyright xxx.com
11  * @description 请求过程日志打印
12  * @create 2021-04-29 20:48:22
13  */
14 @Component
15 public class RestTemplateErrorHandler implements ResponseErrorHandler {
16 
17     @Override
18     public boolean hasError(ClientHttpResponse response) throws IOException {
19         // 返回false表示不管response的status是多少都返回没有错
20         // 这里可以自己定义那些status code你认为是可以抛Error
21         return false;
22     }
23 
24     @Override
25     public void handleError(ClientHttpResponse response) throws IOException {
26         // 这里面可以实现你自己遇到了Error进行合理的处理
27         System.out.println("handleError" + response);
28     }
29 }

在InitBeanConfig的代码中加入

1 @Bean
2 public RestTemplate getRestTemplate() {
3    RestTemplate restTemplate = new RestTemplate();
4    //给所有的Http请求加上请求头
5    restTemplate.setInterceptors(Collections.singletonList(new HeaderRequestInterceptor()));
6    //给请求的返回值加上自己的业务处理
7    restTemplate.setErrorHandler(new RestTemplateErrorHandler());
8    return restTemplate;
9  }

四、给RestTemplate的Get设置RequestBody参数

RestTemplate支持通过setRequestFactory设置HTTP请求客户端工具,支持jdk、httpclient、okHttp等,默认使用的是SimpleClientHttpRequestFactory,该工程使用的JDK实现,底层使用OutputStream来传递body数据,不支持GET传递body。

我们可以修改为httpclient,只需要使用HttpComponentsClientHttpRequestFactory,但是默认的httpclient的GET请求也是不支持传递body的。有两个用于定义Http请求的基础抽象类:HttpRequestBase、HttpEntityEnclosingRequestBase,前者扩展的不能传递body,而后者可以。引入httpClient依赖:

1 <dependency>
2     <groupId>org.apache.httpcomponents</groupId
3     <artifactId>httpclient</artifactId>
4     <version>4.5.13</version>
5 </dependency>

在config文件夹下创建HttpComponentsClientRestfulHttpRequestFactory.java

 1 import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
 2 import org.apache.http.client.methods.HttpUriRequest;
 3 import org.springframework.http.HttpMethod;
 4 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
 5 import org.springframework.stereotype.Component;
 6 
 7 import java.net.URI;
 8 
 9 /**
10  * @author 远猷
11  * @version 1.0.0
12  * @copyright xxx.com
13  * @description 让RestTemplate的GET请求支持RequestBody参数
14  * @create 2021-04-30 09:26:15
15  */
16 @Component
17 public class HttpComponentsClientRestfulHttpRequestFactory extends HttpComponentsClientHttpRequestFactory {
18     @Override
19     protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {
20 
21         if (httpMethod == HttpMethod.GET) {
22             return new HttpGetRequestWithEntity(uri);
23         }
24         return super.createHttpUriRequest(httpMethod, uri);
25     }
26 
27     /**
28      * 定义HttpGetRequestWithEntity实现HttpEntityEnclosingRequestBase抽象类,以支持GET请求携带body数据
29      */
30     private static final class HttpGetRequestWithEntity extends HttpEntityEnclosingRequestBase {
31         public HttpGetRequestWithEntity(final URI uri) {
32             super.setURI(uri);
33         }
34 
35         @Override
36         public String getMethod() {
37             return HttpMethod.GET.name();
38 
39         }
40     }
41 }

在InitBeanConfig的代码中加入

 1 @Bean
 2 public RestTemplate getRestTemplate() {
 3     RestTemplate restTemplate = new RestTemplate();
 4     //给所有的Http请求加上请求头
 5     restTemplate.setInterceptors(Collections.singletonList(new HeaderRequestInterceptor()));
 6     //给请求的返回值加上自己的业务处理
 7     restTemplate.setErrorHandler(new RestTemplateErrorHandler());
 8     //给RestTemplate的get请求加上RequestBody
 9     restTemplate.setRequestFactory(new HttpComponentsClientRestfulHttpRequestFactory());
10     return restTemplate;
11 }

调用方式

1 String requestBody = "param"
2 restTemplate.exchange(url, HttpMethod.GET, new HttpEntity(requestBody, null), Object.class)