Spring最新HTTP接口調用工具RestClient
環(huán)境:SpringBoot3.2.1
1. 簡介
客戶端執(zhí)行HTTP請求,在底層的HTTP客戶端庫(如JDK HttpClient、ApacheHttpComponents等)上公開流暢、同步的API。
RestClient是一個同步HTTP客戶端,它提供了一個現(xiàn)代、流暢的API。它提供了對HTTP庫的抽象,允許從Java對象到HTTP請求的方便轉換,以及從HTTP響應創(chuàng)建對象。
2. 創(chuàng)建RestClient實例
RestClient是使用一個靜態(tài)create方法創(chuàng)建的。還可以通過builder來獲得帶有進一步選項的builder,例如指定使用哪個HTTP庫和使用哪個消息轉換器,設置默認URI、默認路徑變量、默認請求頭或uriBuilderFactory,或注冊攔截器和初始化器。
一旦創(chuàng)建(或構建),RestClient就可以被多個線程安全地使用。
示例:
// 簡單create方式
RestClient defaultClient = RestClient.create() ;
// 通過builder構建
RestClient customClient = RestClient.builder()
.requestFactory(new HttpComponentsClientHttpRequestFactory())
.messageConverters(converters -> converters.add(new PackCustomMessageConverter()))
.baseUrl("http://api.pack.com")
.defaultUriVariables(Map.of("name", "zs"))
.defaultHeader("My-Header", "Foo")
.requestInterceptor(...)
.requestInitializer(...)
.build() ;
3. 使用RestClient
當使用RestClient發(fā)出HTTP請求時,首先要指定使用哪個HTTP方法。這可以使用method(HttpMethod),或者使用便利方法get()、head()、post()等來完成。
RestClient restClient = RestClient.create("http://api.pack.com") ;
restClient.get() ;
restClient.post() ;
// 或
restClient.method(HttpMethod.GET) ;
3.1 Request URI
接下來,可以用URI方法指定請求URI。此步驟是可選的,如果RestClient配置了默認URI,則可以跳過此步驟。URL通常指定為字符串,帶有可選的URI模板變量。默認情況下,字符串url是編碼的,但是可以通過使用自定義uriBuilderFactory構建客戶端來更改。
RestClient restClient = RestClient.create("http://api.pack.com") ;
restClient.method(HttpMethod.GET).uri("/users") ;
3.2 Request Headers And Body
如果有必要,可以通過添加請求頭header(String, String)、header(Consumer<HttpHeaders>),或者使用便利方法accept(MediaType…)、acceptCharset(Charset…)等來操作HTTP請求。對于可以包含正文(POST、PUT和PATCH)的HTTP請求,還有其他方法:contentType(MediaType)和contentLength(long)。
請求體本身可以通過body(Object)設置,它在內部使用HTTP消息轉換。或者,可以使用ParameterizedTypeReference設置請求體,這樣就可以使用泛型。最后,函數(shù)體可以設置為一個回調函數(shù),用于寫入OutputStream。
RestClient restClient = RestClient.create("http://api.pack.com") ;
restClient
.post()
.uri("/users")
.body(new User(666L, "張三", 23))
.header("X-API-VERSION", "1.0")
3.3 獲取響應結果
設置好請求后,調用retrieve()方法訪問HTTP響應。可以使用body(Class)或body(ParameterizedTypeReference)來訪問響應主體,參數(shù)化類型如列表。body方法將響應內容轉換為各種類型,例如bytes可以轉換為字符串,JSON可以使用Jackson轉換為對象等。
響應也可以被轉換為ResponseEntity,以便訪問響應頭和響應體。
RestClient restClient = RestClient.create("http://api.pack.com") ;
restClient
.get()
.uri("/users/666")
.retrieve()
.body(User.class) ;
通過ResponseEntity可以訪問響應的狀態(tài)碼和響應頭:
RestClient restClient = RestClient.create("http://api.pack.com") ;
ResponseEntity<String> result = restClient.get()
.uri("/users/666")
.accept(APPLICATION_JSON)
.retrieve()
.toEntity(User.class) ;
System.out.println("Response status: " + result.getStatusCode());
System.out.println("Response headers: " + result.getHeaders());
System.out.println("Contents: " + result.getBody());
3.4 錯誤處理
默認情況下,當返回的狀態(tài)碼為4xx或5xx的響應時,RestClient會拋出RestClientException的子類。這種行為可以用onStatus來覆蓋。
String result = restClient.get()
.uri("/users/{id}", id)
.retrieve()
// 自定義4xx錯誤
.onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders())
})
.body(String.class) ;
onStatus方法
圖片
3.5 Exchange
對于更高級的場景,RestClient通過exchange方法提供對底層HTTP請求和響應的訪問,可以使用該方法代替retrieve()。使用exchange時不會應用狀態(tài)處理程序,因為exchange方法已經提供了對完整響應的訪問,允許執(zhí)行任何必要的錯誤處理。
RestClient restClient = RestClient.create("http://api.pack.com") ;
restClient
.post()
.uri("/users/666")
.body(new User())
.header("X-API-VERSION", "1.0")
.exchange((request, response) -> {
if (response.getStatusCode().is4xxClientError()) {
throw new RuntimeException(String.format("status: %d, headers: %s", response.getStatusCode(), response.getHeaders())) ;
} else {
return response.getBody() ;
}
}) ;
3.6 客戶端請求工廠
RestClient使用客戶端HTTP庫來執(zhí)行HTTP請求。這些庫通過ClientRequestFactory接口進行調整。有各種可用的實現(xiàn):
- JdkClientHttpRequestFactory for Java’s HttpClient,
- HttpComponentsClientHttpRequestFactory for use with Apache HTTP Components HttpClient,
- JettyClientHttpRequestFactory for Jetty’s HttpClient,
- ReactorNettyClientRequestFactory for Reactor Netty’s HttpClient,
- SimpleClientHttpRequestFactory as a simple default.
如果在構建RestClient時沒有指定請求工廠,它將使用classpath中提供的Apache或Jetty HttpClient。否則,如果加載了java.net.http模塊,它將使用Java的HttpClient。
以上是本篇文章的全部內容,希望對你有幫助。