自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

棄用RestTemplate!RestClient真香

開發(fā) 前端
從Spring Cloud 4.1.0開始RestClient支持服務發(fā)現(xiàn)的負載均衡。在RestTemplate時代,我們在定義RestTemplate bean對象時,只要添加了@LoadBalanced注解,那么我們的RestTemplate就可以通過服務名的方式遠程調用。

環(huán)境:Spring Boot3.2.5

1. 簡介

從Spring Framework 6.1和Spring Boot 3.2開始,我們可以使用Spring       RestClient通過流暢且同步的API執(zhí)行HTTP請求。RestClient基于底層的HTTP客戶端庫工作,如JDK       HttpClient、Apache HttpComponents等。

顧名思義,RestClient提供了WebClient的流暢API設計和RestTemplate的功能。RestClient在設計時就考慮了可測試性,使得在單元測試中模擬HTTP交互變得更加容易。

請注意,對于異步和流式處理場景,WebClient仍然是首選的API。

RestTemplate、RestClient 和 WebClient 如何選擇?

從Spring 6.1開始,與RestTemplate相比,RestClient為同步HTTP訪問提供了更現(xiàn)代的API。RestTemplate是Spring 3中引入的,它是一個臃腫的類,以模板類的形式暴露了HTTP的所有功能,但擁有過多的重載方法。

WebClient也支持同步HTTP訪問,但它需要額外的依賴spring-boot-starter-webflux。而使用RestClient,我們可以避免在項目中添加新的依賴。

RestTemplate:是一個較舊的、用于發(fā)起HTTP請求的同步API。它缺乏新應用程序可能需要的靈活性和現(xiàn)代特性。

WebClient:是Spring WebFlux的反應式、非阻塞客戶端部分。盡管它可以用于同步交互,但對于簡單的用例來說,它似乎有些過于復雜。

RestClient:是Spring框架的新增成員,旨在取代RestTemplate。它提供了一個像WebClient一樣更現(xiàn)代、流暢的API,但不需要反應式堆棧,因此在RestTemplate和WebClient之間找到了一個平衡點。

以下是RestTemplate與WebClient對比:

功能

WebClient

RestTemplate

反應式編程

基于反應式原理構建,支持反應式編程

同步,不是為反應式編程而設計的

技術

基于反應堆棧

基于 Servlet 棧

線程模型

使用非阻塞 I/O,適合處理大量并發(fā)請求

使用阻塞 I/O,在高并發(fā)情況下可能導致線程阻塞

Java版本

需要 Java 8 或更高版本。支持函數(shù)式編程

兼容 Java 6 或更高版本

錯誤處理

使用 onErrorResume、onErrorReturn 等操作符提供強大的錯誤處理功能

錯誤處理通常使用 try-catch 塊進行

流式

使用 Flux 和 Mono 支持流式數(shù)據(jù),適用于反應式流式應用場景

對流的支持有限,不適合反應式流

使用類

最適合微服務、反應式應用程序和需要高并發(fā)性的應用場景

適用于傳統(tǒng)的單片式應用和簡單用例

依賴

需要依賴 Spring WebFlux

需要 Spring Web 依賴關系

功能支持

與反應式編程模式相一致,并有可能得到持續(xù)發(fā)展和支持

可能會進行維護更新,但今后可能不會受到那么多關注

接下來,我將詳細的介紹RestClient的使用。

2. 實戰(zhàn)案例

2.1 創(chuàng)建RestClient

Spring 允許使用多種靈活的方法來初始化 RestClient Bean。例如,最簡單的方法是使用 create() 方法。

@Value("${pack.remote.address:http://www.pack.com}")
private String baseURI;
@Bean
public RestClient restClient() {
  return RestClient.create(baseURI) ;
}

我們還可以使用 builder() 方法來設置更復雜的選項,如默認頭、請求處理器、消息處理程序等。例如,下面的配置使用 HttpClient 作為 HTTP 連接管理的底層庫。

@Bean
public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
  HttpComponentsClientHttpRequestFactory clientHttpRequestFactory
    = new HttpComponentsClientHttpRequestFactory() ;
  clientHttpRequestFactory.setHttpClient(httpClient) ;
  // 更多配置
  return clientHttpRequestFactory ;
}
@Bean
public RestClient restClient(CloseableHttpClient httpClient) {
  return RestClient.builder()
    .baseUrl(baseURI)
    // 更多配置
    .requestFactory(clientHttpRequestFactory())
    .build() ;
}

甚至,我們還可以直接通過RestTemplate來構建RestClient對象

@Bean
public RestClient restClient(RestTemplate restTemplate) {
  return RestClient.create(restTemplate);
}

2.2 HTTP Get請求

restClient.get() 用于向指定的 URL 創(chuàng)建 GET 請求。請注意,我們可以將動態(tài)值傳遞給 URI 模板。

@Resource
private RestClient restClient ;
restClient.get()
  .uri("/users")
  //...
restClient.get()
  .uri("/employees/{id}", id)
  //...

最后,retrieve() 方法發(fā)送請求并返回包含 API 響應的 ResponseSpec。下面的請求將獲取用戶列表,并將響應體解析為User實例列表。

List<User> list = restClient.get()
  .uri("/users")
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .body(List.class) ;

我們還可以處理,如請求的狀態(tài)、請求header等數(shù)據(jù),可以按如下方式獲取響應實體(ResponseEntity):

ResponseEntity<List> responseEntity = restClient.get()
  .uri("/users")
  .accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .toEntity(List.class) ;

2.3 HTTP Post請求

restClient.post() 用于處理 POST 請求。除了 POST API 通常不返回任何響應外,其他大部分與 GET API 調用相同。toBodilessEntity() 方法具有完全相同的功能,可用于 POST API。

User user = new User(666L, "張三", 22) ;
ResponseEntity<Void> responseEntity = restClient.post()
  .uri("/users")
  .contentType(MediaType.APPLICATION_JSON)
  .body(user)
  .retrieve()
  .toBodilessEntity() ;

2.4 HTTP Put請求

restClient.put() 用于處理 PUT 請求。PUT API 通常會發(fā)送一個請求正文并接收一個響應正文,如下示例。

User user = new User(666L, "張三", 22) ;
ResponseEntity<User> responseEntity = restClient.put()
  .uri("/users/666")
  .contentType(MediaType.APPLICATION_JSON)
  .accept(MediaType.APPLICATION_JSON)
  .body(user)
  .retrieve()
  .toEntity(User.class) ;

2.5 HTTP Delete請求

restClient.delete() 用于處理 DELETE 請求。一般來說,delete API 在服務器中接受,并且不會要求響應體。

ResponseEntity<Employee> responseEntity = restClient.delete()
  .uri("/users/666")
  .retrieve()
  .toBodilessEntity() ;

2.6 RestClient復雜應用

如果我們需要完全控制響應處理,可以使用 exchange() 方法。它提供了對 HttpRequest 和 HttpResponse 對象的訪問權限,然后我們就可以按自己的需要使用它們了。

List<Employee> list = restClient.get()
  .uri("/users")
  .accept(MediaType.APPLICATION_JSON)
  .exchange((request, response) -> {
    List response = null ;
    if (response.getStatusCode().is4xxClientError()
        || response.getStatusCode().is5xxServerError()) {
      System.err.println("請求錯誤") ;
    } else {
      response = new ObjectMapper().readValue(response.getBody(), List.class) ;
    }
    return response ;
  }) ;

2.7 異常處理

對于失敗的請求,RestClient 會拋出兩種異常:

HttpClientErrorException:帶 4xx 響應代碼

HttpServerErrorException:響應代碼為 5xx

try {
  User user = restClient.get()
    .uri("/users/666")
    .accept(MediaType.APPLICATION_JSON)
    .retrieve()
    .body(User.class) ;
} catch(HttpClientErrorException e4xx) {
  // ...
} catch(HttpServerErrorException e5xx) {
  // ...
}

2.8 自定義攔截器

我們可以通過RestClient.Builder設置攔截器,通過攔截器我們可以進行日志的記錄,認證的配置等等,如下示例:

@Bean
public RestClient demoRestClient(LoggingRestClientInterceptor loggingInterceptor) {
  return RestClient
    .builder()
    .requestInterceptor(loggingInterceptor)
    .build() ;
}

自定義攔截器

@Component
public static class LoggingRestClientInterceptor implements ClientHttpRequestInterceptor {
  @Override
  public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
      throws IOException {
    System.err.println("logging...") ;
    return execution.execute(request, body) ;
  }
}

注:RestTemplate與RestClient使用的攔截器是相同的。所以你可以復用之前寫的攔截器。

2.9 基于服務發(fā)現(xiàn)負載均衡

從Spring Cloud 4.1.0開始RestClient支持服務發(fā)現(xiàn)的負載均衡。在RestTemplate時代,我們在定義RestTemplate bean對象時,只要添加了@LoadBalanced注解,那么我們的RestTemplate就可以通過服務名的方式遠程調用。

RestClient要通過服務發(fā)現(xiàn)機制調用,那么我們就要自定義RestClient.Builder對象。

@Bean
@LoadBalanced
public RestClient.Builder demoRestClientBuilder() {
  Builder builder = RestClient.builder().baseUrl("http://demo") ;
  return builder ;
}

接下來,我們就可以通過上面自定義的RestClient.Builder來構建RestClient。

@Bean
public RestClient lbcRestClient(RestClient.Builder builder) {
  return builder
    .baseUrl("http://demo")
    .build() ;
}

這樣配置,我們的RestClient就具備服務發(fā)現(xiàn)的能力了。

責任編輯:武曉燕 來源: Spring全家桶實戰(zhàn)案例源碼
相關推薦

2020-12-03 18:29:30

KubernetesDocker容器

2024-10-17 14:14:29

2023-10-12 07:46:02

2011-03-23 09:40:37

Google GearChrome

2022-06-03 09:41:03

DockerKubernetes容器

2022-04-08 16:14:21

FedoraBIOS32 位操作系統(tǒng)

2023-09-22 16:54:42

GNOME 45系統(tǒng)

2021-06-04 05:21:19

KubernetesDocker容器

2024-06-27 13:45:21

2010-05-20 14:37:34

紅帽Xen

2011-08-05 09:59:04

GNOME 3Linus TorvaXfce

2020-10-28 07:03:11

NodeSassDart Sass

2020-12-18 09:23:41

KubernetesDocker

2022-02-22 14:07:07

框架配置類Spring

2018-09-10 15:40:46

GitHubQuery前端

2020-05-15 08:30:25

前端開發(fā)工具

2016-01-08 13:39:27

2010-03-30 09:04:41

2010-01-13 09:49:34

微軟windowsLinux

2011-12-26 09:38:24

諾基亞SymbianBelle
點贊
收藏

51CTO技術棧公眾號