網(wǎng)頁設計代碼模板網(wǎng)站企業(yè)網(wǎng)上的推廣
自 Spring 5 以來,WebClient已成為Spring WebFlux的一部分,并且是發(fā)出 HTTP 請求的首選方式。它是經(jīng)典RestTemplate的首選替代方案,后者自 Spring 5.0 以來一直處于維護模式。
本文將討論 Spring?WebClient和RestTemplate類之間的主要區(qū)別。
1. WebClient和RestTemplate快速比較
特征 | 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ā)和支持。 | 可能會維護更新,將來可能不會受到那么多關注。 |
2. 阻塞RestTemplate與非阻塞WebClient對比
2.1.RestTemplate
RestTemplate本質(zhì)上是阻塞的,并使用 Java Servlet API 的每個請求一個線程模型。這意味著RestTemplate一旦向遠程服務器發(fā)送請求,就會等待響應。默認情況下,每次RestTemplate都會創(chuàng)建新的,并在收到并處理響應后關閉連接。Httpconnection 創(chuàng)建和關閉 URL 連接是一項成本高昂的操作。為了在生產(chǎn)類應用程序中有效地使用RestTemplate ,我們必須使用HTTP 連接池,否則性能會快速下降。當應用程序中有大量請求時,線程和連接的數(shù)量也會按比例增加。這會給服務器資源帶來負擔。如果服務器速度緩慢,用戶很快就會發(fā)現(xiàn)應用程序性能下降,甚至無響應。
請注意,RestTemplate 是線程安全的,并且可以隨時在多個連接之間共享單個實例。
@Service
public class MyService {private final RestTemplate restTemplate;@Autowiredpublic MyService(RestTemplate restTemplate) {this.restTemplate = restTemplate;}public String getData() {ResponseEntity<String> responseEntity= restTemplate.getForEntity("https://api.example.com/data", String.class);String responseBody = responseEntity.getBody();return responseBody;}
}
2.2.WebClient
與RestTemplate相反,WebClient本質(zhì)上是異步且非阻塞的。它遵循 Spring WebFlux 反應式框架的事件驅(qū)動架構。使用WebClient,客戶端無需等待響應返回。相反,當服務器有響應時,它將使用回調(diào)方法收到通知。
當我們通過WebClient調(diào)用返回 Mono或 Flux 的API 時,API 會立即返回。而調(diào)用結(jié)果將通過 mono 或 flux 回調(diào)傳遞給調(diào)用端。
請注意,如果需要,我們可以通過WebClient.block()方法實現(xiàn)類似RestTemplate的同步處理。
@Service
public class MyService {private final WebClient webClient;@Autowiredpublic MyService(WebClient webClient) {this.webClient = webClient;}public Mono<String> getData() {return webClient.get().uri("/data").retrieve().bodyToMono(String.class).subscribe(// onSuccess callbackresult -> {System.out.println("Success: " + result);},// onError callbackerror -> {System.err.println("Error: " + error.getMessage());});}
}
3.結(jié)論
從上面可以清楚地看出, WebClient和RestTemplate之間唯一的大區(qū)別是它們的阻塞性質(zhì)。RestTemplate會阻止請求線程,而WebClient不會。我們可以使用WebClient來發(fā)出同步請求,但反之則不行。RestTemplate無法發(fā)出異步請求。
雖然WebClient是未來使用的首選方式,但 RestTemplate?應該會長期保留,盡管沒有添加任何新的核心功能。
在考慮使用WebClient?構建新應用程序時,我們必須記住,要構建真正的非阻塞應用程序,必須以非阻塞方式創(chuàng)建/使用其所有組件,即客戶端、控制器、中間服務,甚至數(shù)據(jù)庫。如果其中之一阻塞了請求,目的就會落空。