RestTemplate的一些坑和改造點


一、RestTemplate怎么引入和使用

在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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM