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

Spring6提供的四種遠(yuǎn)程接口調(diào)用神器!你知道那種?

開發(fā) 前端
實(shí)現(xiàn)遠(yuǎn)程接口調(diào)用方面的強(qiáng)大功能。無論是使用WebClient、RestTemplate、HTTP Interface還是直接使用RestClient,Spring都提供了豐富的工具和接口來簡(jiǎn)化開發(fā)者的操作。

1. 介紹

Spring 6是一個(gè)非常強(qiáng)大的框架,它提供了許多工具和接口來簡(jiǎn)化遠(yuǎn)程接口調(diào)用。其中,WebClient、RestTemplate、HTTP Interface和RestClient是四種方式。

WebClient是Spring 5中新引入的一個(gè)接口基于響應(yīng)式,它提供了一種更簡(jiǎn)單、更靈活的方式來調(diào)用遠(yuǎn)程接口。與RestTemplate相比,WebClient更加現(xiàn)代化,具有更好的性能和更低的內(nèi)存占用。

RestTemplate是Spring 3中引入的一個(gè)接口,它提供了一種更加簡(jiǎn)單、更加直觀的方式來調(diào)用遠(yuǎn)程接口。雖然WebClient是更現(xiàn)代化的選擇,但RestTemplate仍然是一種常用的遠(yuǎn)程接口調(diào)用方式。

HTTP Interface將 HTTP 服務(wù)定義為一個(gè) Java 接口,其中包含用于 HTTP 交換的注解方法。然后,你可以生成一個(gè)實(shí)現(xiàn)該接口并執(zhí)行交換的代理。這有助于簡(jiǎn)化 HTTP 遠(yuǎn)程訪問,因?yàn)檫h(yuǎn)程訪問通常需要使用一個(gè)門面來封裝使用底層 HTTP 客戶端的細(xì)節(jié)。

RestClient是一個(gè)同步 HTTP 客戶端,提供現(xiàn)代、流暢的 API。它為 HTTP 庫提供了一個(gè)抽象,可以方便地從 Java 對(duì)象轉(zhuǎn)換為 HTTP 請(qǐng)求,并從 HTTP 響應(yīng)創(chuàng)建對(duì)象。

下面分別介紹4個(gè)REST接口調(diào)用的詳細(xì)使用。

2. 遠(yuǎn)程接口調(diào)用

RestTemplate

RestTemplate 提供了比 HTTP 客戶端庫更高級(jí)別的 API。它使調(diào)用 REST 端點(diǎn)變得簡(jiǎn)單易行。它公開了以下幾組重載方法:

方法

描述

getForObject

通過GET檢索數(shù)據(jù)。

getForEntity

使用 GET 獲取響應(yīng)實(shí)體(即狀態(tài)、標(biāo)頭和正文)。

headForHeaders

使用 HEAD 讀取資源的所有標(biāo)頭。

postForLocation

使用 POST 創(chuàng)建新資源,并從響應(yīng)中返回位置標(biāo)頭。

postForObject

使用 POST 創(chuàng)建一個(gè)新資源,并從響應(yīng)中返回描述。

postForEntity

使用 POST 創(chuàng)建一個(gè)新資源,并從響應(yīng)中返回描述。

put

使用 PUT 創(chuàng)建或更新資源。

patchForObject

使用 PATCH 更新資源,并返回響應(yīng)中的描述。請(qǐng)注意,JDK HttpURLConnection 不支持 PATCH,但 Apache HttpComponents 和其他組件支持。

delete

使用 DELETE 刪除指定 URI 上的資源。

optionsForAllow

通過 ALLOW 讀取資源允許使用的 HTTP 方法。

exchange

前述方法的更通用(更少意見)版本,可在需要時(shí)提供額外的靈活性。它接受一個(gè) RequestEntity(包括作為輸入的 HTTP 方法、URL、標(biāo)題和正文),并返回一個(gè) ResponseEntity。

這些方法允許使用參數(shù)化類型引用(ParameterizedTypeReference)而不是類(Class)來指定具有泛型的響應(yīng)類型。

execute

執(zhí)行請(qǐng)求的最通用方式,可通過回調(diào)接口完全控制請(qǐng)求準(zhǔn)備和響應(yīng)提取。

  • 初始化

默認(rèn)構(gòu)造函數(shù)使用 java.net.HttpURLConnection 來執(zhí)行請(qǐng)求。你可以通過 ClientHttpRequestFactory 的實(shí)現(xiàn)切換到不同的 HTTP 庫。目前,該程序還內(nèi)置了對(duì) Apache HttpComponents 和 OkHttp 的支持。示例:

RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

每個(gè) ClientHttpRequestFactory 都會(huì)公開底層 HTTP 客戶端庫的特定配置選項(xiàng),例如,憑證、連接池和其他細(xì)節(jié)。

  • URIs

許多 RestTemplate 方法都接受 URI 模板和 URI 模板變量,可以是字符串變量參數(shù),也可以是 Map<String,String>。

String result = restTemplate.getForObject(
    "http://pack.com/users/{userId}", String.class, 666) ;

Map<String, ?>方式:

Map<String, Object> params = Collections.singletonMap("userId", 666);


String result = restTemplate.getForObject(
    "http://pack.com/users/{userId}", String.class, params) ;
  • Headers

可以使用 exchange() 方法指定請(qǐng)求頭,如下例所示:

String uriTemplate = "http://pack.com/users/{userId}";
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42);


RequestEntity<Void> requestEntity = RequestEntity.get(uri)
    .header("x-api-token", "aabbcc")
    .build() ;
ResponseEntity<String> response = template.exchange(requestEntity, String.class);
String responseHeader = response.getHeaders().getFirst("x-version");
String body = response.getBody() ;
  • body

如果你當(dāng)前CLASSPATH存在MappingJackson2HttpMessageConverter,那么你可以直接將請(qǐng)求結(jié)果映射為你所需要的結(jié)果對(duì)象,如下示例所示,將目標(biāo)接口返回值直接轉(zhuǎn)換為User對(duì)象。

User user = restTemplate.getForObject("http://pack.com/users/{userId}", User.class, 666);

默認(rèn)情況下,RestTemplate 會(huì)注冊(cè)所有內(nèi)置的消息轉(zhuǎn)換器,這決定于你當(dāng)前類路徑是否有相應(yīng)的轉(zhuǎn)換庫。你也可以顯式設(shè)置要使用的消息轉(zhuǎn)換器。默認(rèn)構(gòu)造函數(shù)如下:

public RestTemplate() {
  this.messageConverters.add(new ByteArrayHttpMessageConverter());
  this.messageConverters.add(new StringHttpMessageConverter());
  this.messageConverters.add(new ResourceHttpMessageConverter(false));
  // ...其它轉(zhuǎn)換器
  if (jackson2Present) {
    this.messageConverters.add(new MappingJackson2HttpMessageConverter());
  }
  else if (gsonPresent) {
    this.messageConverters.add(new GsonHttpMessageConverter());
  }
  else if (jsonbPresent) {
    this.messageConverters.add(new JsonbHttpMessageConverter());
  }
  // ...其它轉(zhuǎn)換器
  this.uriTemplateHandler = initUriTemplateHandler();
}

注意:RestTemplate 目前處于維護(hù)模式,只接受小改動(dòng)和錯(cuò)誤請(qǐng)求。請(qǐng)考慮改用 WebClient。

WebClient

WebClient 是執(zhí)行 HTTP 請(qǐng)求的非阻塞、反應(yīng)式客戶端。它在 5.0 中引入,提供了 RestTemplate 的替代方案,支持同步、異步和流場(chǎng)景。

WebClient 支持以下功能:

  1. 非阻塞 I/O。
  2. 反應(yīng)流反向壓力
  3. 用更少的硬件資源實(shí)現(xiàn)高并發(fā)。
  4. 利用 Java 8 lambdas 的函數(shù)式流暢應(yīng)用程序接口。
  5. 同步和異步交互。
  6. 服務(wù)器上的數(shù)據(jù)流或服務(wù)器下的數(shù)據(jù)流。

示例:

Mono<Person> result = client.get()
  .uri("/users/{userId}", id).accept(MediaType.APPLICATION_JSON)
  .retrieve()
  .bodyToMono(User.class);

HTTP Interface

Spring Framework 可讓你將 HTTP 服務(wù)定義為一個(gè) Java 接口,其中包含用于 HTTP 交換的注解方法。然后,你可以生成一個(gè)實(shí)現(xiàn)該接口并執(zhí)行交換的代理。這有助于簡(jiǎn)化 HTTP 遠(yuǎn)程訪問,因?yàn)檫h(yuǎn)程訪問通常需要使用一個(gè)門面來封裝使用底層 HTTP 客戶端的細(xì)節(jié)。

首先,聲明一個(gè)帶有 @HttpExchange 方法的接口:

@HttpExchange(url = "/demos")
public interface DemoInterface {


  @PostExchange("/format3/{id}")
  Users queryUser(@PathVariable Long id);


}

創(chuàng)建一個(gè)代理,執(zhí)行所聲明的 HTTP exchanges:

@Service
public class DemoService {


  private final DemoInterface demoInterface ;


  public DemoService() {
    // 基于響應(yīng)式調(diào)用;你當(dāng)前的環(huán)境需要引入webflux
    WebClient client = WebClient.builder().baseUrl("http://localhost:8088/").build() ;
    HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build() ;
    this.demoInterface = factory.createClient(DemoInterface.class) ;
  }


  public Users queryUser(Long id) {
    return this.demoInterface.queryUser(id) ;
  }


}

測(cè)試接口

@Resource
private DemoService demoService ;




@GetMapping("/{id}")
public Users getUser(@PathVariable("id") Long id) {
  return this.demoService.queryUser(id) ;
}

執(zhí)行結(jié)果

圖片圖片

支持的方法參數(shù)

方法參數(shù)

說明

URI

動(dòng)態(tài)設(shè)置請(qǐng)求的 URL,覆蓋注解的 url 屬性。

HttpMethod

動(dòng)態(tài)設(shè)置請(qǐng)求的 HTTP 方法,覆蓋注解的方法屬性

@RequestHeader

添加一個(gè)或多個(gè)請(qǐng)求標(biāo)頭。參數(shù)可以是包含多個(gè)標(biāo)頭的 Map<String, ?> 或 MultiValueMap<String, ?>、值集合<?> 或單個(gè)值。

@PathVariable

添加一個(gè)變量,用于擴(kuò)展請(qǐng)求 URL 中的占位符。參數(shù)可以是包含多個(gè)變量的 Map<String, ?> 或單個(gè)值。

@RequestBody

提供請(qǐng)求的正文,既可以是要序列化的對(duì)象,也可以是 Reactive Streams Publisher(如 Mono、Flux 或通過配置的 ReactiveAdapterRegistry 支持的任何其他異步類型)。

@RequestParam

添加一個(gè)或多個(gè)請(qǐng)求參數(shù)。參數(shù)可以是包含多個(gè)參數(shù)的 Map<String, ?> 或 MultiValueMap<String, ?>、數(shù)值集合<?> 或單個(gè)數(shù)值。

當(dāng) "content-type"設(shè)置為 "application/x-www-form-urlencoded "時(shí),請(qǐng)求參數(shù)將在請(qǐng)求正文中編碼。否則,它們將作為 URL 查詢參數(shù)添加。

@RequestPart

添加一個(gè)請(qǐng)求部分,它可以是字符串(表單字段)、資源(文件部分)、對(duì)象(要編碼的實(shí)體,如 JSON)、HttpEntity(部分內(nèi)容和標(biāo)頭)、Spring 部分或上述任何部分的 Reactive Streams 發(fā)布器。

@CookieValue

添加一個(gè)或多個(gè) cookie。參數(shù)可以是包含多個(gè) cookie 的 Map<String, ?> 或 MultiValueMap<String, ?>、值集合<?> 或單個(gè)值。

支持的返回值

返回值

說明

voidMono<Void>

執(zhí)行給定的請(qǐng)求,并發(fā)布響應(yīng)內(nèi)容(如果有)。

HttpHeaders
Mono<HttpHeaders>

執(zhí)行給定的請(qǐng)求,釋放響應(yīng)內(nèi)容(如果有),并返回響應(yīng)標(biāo)頭。

<T>Mono<T>

執(zhí)行給定的請(qǐng)求,并根據(jù)聲明的返回類型對(duì)響應(yīng)內(nèi)容進(jìn)行解碼。

<T>Flux<T>

執(zhí)行給定的請(qǐng)求,并將響應(yīng)內(nèi)容解碼為已聲明元素類型的數(shù)據(jù)流。

ResponseEntity<Void>
Mono<ResponseEntity<Void>>

執(zhí)行給定的請(qǐng)求,釋放響應(yīng)內(nèi)容(如果有),并返回一個(gè)包含狀態(tài)和標(biāo)頭的 ResponseEntity。

ResponseEntity<T>,
Mono<ResponseEntity<T>>

執(zhí)行給定的請(qǐng)求,按照聲明的返回類型解碼響應(yīng)內(nèi)容,并返回一個(gè)包含狀態(tài)、標(biāo)頭和解碼后正文的 ResponseEntity。

Mono<ResponseEntity<Flux<T>>

執(zhí)行給定的請(qǐng)求,將響應(yīng)內(nèi)容解碼為已聲明元素類型的數(shù)據(jù)流,并返回一個(gè)包含狀態(tài)、標(biāo)頭和解碼后的響應(yīng)正文數(shù)據(jù)流的 ResponseEntity。

異常處理

默認(rèn)情況下,WebClient為4xx和5xx HTTP狀態(tài)代碼引發(fā)WebClientResponseException。要自定義此項(xiàng),可以注冊(cè)響應(yīng)狀態(tài)處理程序,該處理程序應(yīng)用于通過客戶端執(zhí)行的所有響應(yīng):

WebClient client = WebClient.builder()
    // 狀態(tài)碼為4xx或5xx
    .defaultStatusHandler(HttpStatusCode::isError, resp -> Mono.just(new RuntimeException(resp.statusCode().toString() + "請(qǐng)求錯(cuò)誤")))
    .baseUrl("http://localhost:8088/").build() ;
HttpServiceProxyFactory factory = HttpServiceProxyFactory
    .builder(WebClientAdapter.forClient(client)).build() ;

RestClient

該接口是在Spring6.1.1版本中才有的,是一個(gè)同步 HTTP 客戶端,提供現(xiàn)代、流暢的 API。

創(chuàng)建RestClientRestClient 是通過靜態(tài)創(chuàng)建方法之一創(chuàng)建的。你還可以使用 builder 獲取帶有更多選項(xiàng)的生成器,例如指定要使用的 HTTP 庫和要使用的消息轉(zhuǎn)換器,設(shè)置默認(rèn) URI、默認(rèn)路徑變量、默認(rèn)請(qǐng)求頭,或注冊(cè)攔截器和初始化器。

創(chuàng)建(或構(gòu)建)后,RestClient 可由多個(gè)線程安全使用。

// 默認(rèn)通過靜態(tài)方法創(chuàng)建
RestClient restClient = RestClient.create();
// 自定義方式
RestClient restClient = RestClient.builder()
  .requestFactory(new HttpComponentsClientHttpRequestFactory())
  // 自定義消息轉(zhuǎn)換器
  // .messageConverters(converters -> converters.add(new PackCustomMessageConverter()))
  .baseUrl("http://localhost:8088")
  .defaultUriVariables(Map.of("id", "888"))
  .defaultHeader("x-api-token", "aabbcc")
  .requestInterceptor(new ClientHttpRequestInterceptor() {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
        throws IOException {
      System.out.println("我是攔截器") ;
      return execution.execute(request, body) ;
    }
  })
  .requestInitializer(new ClientHttpRequestInitializer() {
    @Override
    public void initialize(ClientHttpRequest request) {
      System.out.println("我是初始化器") ;
      request.getHeaders().add("x-version", "1.0.0") ;
    }
  })
  .build() ;

調(diào)用及處理返回值

Users users = customClient.get()
  .uri("/demos/users/{id}")
  .retrieve()
  .body(Users.class) ;

post+body請(qǐng)求方式

Users user = new Users();
ResponseEntity<Void> response = restClient.post() 
  .uri("/demos/users") 
  .contentType(APPLICATION_JSON) 
  .body(user) 
  .retrieve()
  .toBodilessEntity() ;

錯(cuò)誤處理默認(rèn)情況下,當(dāng)返回狀態(tài)代碼為 4xx 或 5xx 的響應(yīng)時(shí),RestClient 會(huì)拋出 RestClientException 的子類??梢允褂?onStatus.RestClientException 命令重寫該行為。

Users users = customClient.get()
  .uri("/demos/users/{id}")
  .retrieve()
  // 處理返回狀態(tài)碼為:4xx和5xx
  .onStatus(HttpStatusCode::isError, (request, response) -> {
    throw new RuntimeException(response.getStatusCode().toString() + "請(qǐng)求錯(cuò)誤") ;
  })
  .body(Users.class) ;

總結(jié):實(shí)現(xiàn)遠(yuǎn)程接口調(diào)用方面的強(qiáng)大功能。無論是使用WebClient、RestTemplate、HTTP Interface還是直接使用RestClient,Spring都提供了豐富的工具和接口來簡(jiǎn)化開發(fā)者的操作。這些工具和接口不僅具有高性能、低內(nèi)存占用的優(yōu)點(diǎn),而且提供了良好的可擴(kuò)展性和靈活性,使得開發(fā)者可以根據(jù)實(shí)際需求進(jìn)行定制化開發(fā)。

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

2024-03-12 08:29:28

C++類型轉(zhuǎn)換方式

2024-11-04 09:39:08

Java?接口Thread?類

2024-08-29 09:01:39

2017-04-07 12:30:38

2020-12-09 11:21:48

大數(shù)據(jù)數(shù)據(jù)分析

2020-12-09 10:56:15

業(yè)務(wù)分析數(shù)據(jù)分析大數(shù)據(jù)

2009-11-06 14:25:56

WCF接口

2025-04-01 00:18:55

2020-07-24 09:56:12

React開發(fā)數(shù)據(jù)

2022-11-04 13:35:29

IT遠(yuǎn)程工作混合工作

2020-06-17 08:31:10

權(quán)限控制Spring Secu

2021-07-27 10:49:10

SpringSecurity權(quán)限

2022-09-19 15:57:36

JVM對(duì)象緩存

2009-06-22 11:01:12

2023-06-19 15:38:38

JavaScripAPI

2022-10-13 08:02:13

死鎖運(yùn)算系統(tǒng)

2025-01-21 00:00:00

權(quán)限模型RBAC

2025-01-15 12:43:23

2022-03-14 09:05:37

Spring項(xiàng)目處理器

2024-06-24 01:00:00

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)