最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot WebClient 全面解析

 更新時(shí)間:2026年05月25日 09:51:32   作者:西涼的悲傷  
WebClient是Spring5非阻塞響應(yīng)式HTTP客戶(hù)端,適用于高并發(fā)場(chǎng)景和微服務(wù)通信,替代RestTemplate更推薦新項(xiàng)目,支持異步并發(fā)請(qǐng)求和鏈?zhǔn)紸PI風(fēng)格,這篇文章給大家介紹SpringBoot WebClient全面解析,感興趣的朋友一起看看吧

一、什么是 WebClient?

WebClient 是 Spring 5 引入的一個(gè)現(xiàn)代 HTTP 客戶(hù)端,屬于 Spring WebFlux 模塊,用來(lái)發(fā)送 HTTP 請(qǐng)求(GET、POST、PUT、DELETE 等)。
它可以替代傳統(tǒng)的 RestTemplate。(Home)

WebClient 它底層基于:

  • Reactor
  • Netty
  • NIO

因此:

少量線(xiàn)程
處理大量請(qǐng)求

這也是它高并發(fā)能力強(qiáng)的原因。(Home)

官方文檔:

二、 WebClient 能解決什么問(wèn)題?

它主要用于:

  • 調(diào)用第三方接口
  • 微服務(wù)之間通信
  • 下載文件
  • 上傳文件
  • 調(diào)用 AI / OpenAPI 接口
  • 高并發(fā) HTTP 請(qǐng)求
  • 異步并發(fā)調(diào)用多個(gè)接口

例如:

你的系統(tǒng)
   ↓
WebClient
   ↓
支付寶接口 / 微信接口 / 第三方系統(tǒng)

三、WebClient 和 RestTemplate 的區(qū)別

對(duì)比項(xiàng)WebClientRestTemplate
所屬Spring WebFluxSpring MVC
是否異步支持默認(rèn)同步阻塞
是否非阻塞
是否支持響應(yīng)式支持 Mono / Flux不支持
并發(fā)能力一般
是否支持流式處理支持一般
推薦程度新項(xiàng)目推薦維護(hù)模式
API 風(fēng)格鏈?zhǔn)?fluent API模板式 API

Spring 官方已經(jīng)說(shuō)明:

  • RestTemplate 進(jìn)入 maintenance mode(維護(hù)模式)
  • 新項(xiàng)目更推薦 WebClient (Reddit)

四、WebClient 的核心優(yōu)勢(shì)

1. 非阻塞(Non-Blocking)

傳統(tǒng) RestTemplate:

線(xiàn)程發(fā)請(qǐng)求
↓
一直等待響應(yīng)
↓
線(xiàn)程被占用

WebClient:

線(xiàn)程發(fā)請(qǐng)求
↓
不用等待
↓
線(xiàn)程去處理別的任務(wù)
↓
響應(yīng)回來(lái)再通知

因此:

  • 更省線(xiàn)程
  • 更適合高并發(fā)
  • 更適合微服務(wù)

支持同步調(diào)用

WebClient 雖然是響應(yīng)式的,但你也能:

.block()

變成同步調(diào)用。

因此:

即使你不是響應(yīng)式項(xiàng)目,也能使用 WebClient。

2. 支持異步

可以同時(shí)請(qǐng)求多個(gè)接口:

Mono<User> userMono = webClient.get()...
Mono<Order> orderMono = webClient.get()...

最后組合:

Mono.zip(userMono, orderMono)

3. 鏈?zhǔn)?API 更現(xiàn)代

傳統(tǒng)的 RestTemplate:

restTemplate.exchange(...)

而 WebClient:

webClient.get()
         .uri("/user")
         .retrieve()
         .bodyToMono(User.class);

更像:

  • Java8 Stream
  • 函數(shù)式編程
  • Reactor 響應(yīng)式風(fēng)格

五、WebClient 的核心對(duì)象

最重要的:

WebClient

它類(lèi)似:

瀏覽器客戶(hù)端

負(fù)責(zé):

  • 發(fā)請(qǐng)求
  • 設(shè)置 header
  • 設(shè)置 token
  • 接收響應(yīng)
  • 下載文件

六、Mono 和 Flux 是什么?

WebClient 基于 Reactor。

兩個(gè)核心類(lèi):

類(lèi)型含義
Mono0~1 個(gè)結(jié)果
Flux0~N 個(gè)結(jié)果

例如:

Mono<User>
Flux<User>

表示:

Mono<User>表示未來(lái)會(huì)返回一個(gè) User
Flux<User>表示未來(lái)會(huì)返回多個(gè) User

七、如何引入 WebClient?

Maven

Spring Boot 項(xiàng)目:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

即使你項(xiàng)目不是 WebFlux 項(xiàng)目,也能單獨(dú)使用 WebClient。

八、WebClient 的基本創(chuàng)建方式

1. 創(chuàng)建 WebClient 最簡(jiǎn)單的使用方式

WebClient webClient = WebClient.create();

或者:

WebClient webClient = WebClient.create("https://api.example.com");

或者:

WebClient webClient = WebClient.builder()
        .baseUrl("https://api.example.com")
        .build();

2.Spring Bean 配置類(lèi)方式(推薦)

配置類(lèi)

@Configuration
public class WebClientConfig {
    @Bean
    public WebClient webClient() {
        //配置超時(shí)和日志
        HttpClient httpClient = HttpClient.create()
            .responseTimeout(Duration.ofSeconds(10))
            .wiretap(true);
        return WebClient.builder()
                //基本url域名
                .baseUrl("https://api.example.com")
            	//默認(rèn)請(qǐng)求頭增加類(lèi)型為json
                .defaultHeader(HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_JSON_VALUE)
                //默認(rèn)請(qǐng)求頭增加token
        		.defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer abcdefg")
            	//超時(shí)配置和日志
            	.clientConnector(new ReactorClientHttpConnector(httpClient))
                .build();
    }
}

通常 token 是動(dòng)態(tài)獲取的,可以使用 filter,下面的示例使用 getToken() 動(dòng)態(tài)獲取 token。

Filter 示例

@Bean
public WebClient webClient() {
    return WebClient.builder()
            .filter((request, next) -> {
                ClientRequest newRequest =
                        ClientRequest.from(request)
                                .header(HttpHeaders.AUTHORIZATION,"Bearer " + getToken())
                                .build();
                return next.exchange(newRequest);})
            .build();
}

官方 builder 配置項(xiàng)包括:

  • baseUrl
  • defaultHeader
  • filter
  • codec
  • timeout
  • connector 等 (Spring 框架)

注入使用

@Autowired
private WebClient webClient;

九、GET 帶參數(shù)

請(qǐng)求

GET /user?page=1&size=10

代碼

String result = webClient.get()
        .uri(uriBuilder -> uriBuilder
                .path("/user")
                .queryParam("page", 1)
                .queryParam("size", 10)
                .build())
        .headers(headers -> {
            headers.setBearerAuth(token);
            headers.add("appId", "1001");})
        .retrieve()
        .bodyToMono(String.class)
        .block();

最終請(qǐng)求:

https://api.example.com/user?page=1&size=10

get()

表示 GET 請(qǐng)求:

webClient.get()

uri()

請(qǐng)求地址。

如果請(qǐng)求地址很簡(jiǎn)單可以這樣寫(xiě):

.uri("/user")

headers()

增加請(qǐng)求頭,可以在配置類(lèi)里配置默認(rèn)的請(qǐng)求頭

retrieve()

開(kāi)始發(fā)送請(qǐng)求并獲取響應(yīng):

.retrieve()

bodyToMono()

響應(yīng)轉(zhuǎn)對(duì)象:

.bodyToMono(String.class)

block()

阻塞等待結(jié)果:

.block();

注意:

WebClient 本身是異步的。

調(diào)用:

.block()

才會(huì)變成同步等待。

十、GET 返回對(duì)象

User 類(lèi)

@Data
public class User {
    private Long id;
    private String name;
}

調(diào)用

User user = webClient.get()
        .uri("/user")
        .retrieve()
        .bodyToMono(User.class)
        .block();

如果帶參數(shù)和請(qǐng)求頭:

User user = webClient.get()
         .uri(uriBuilder -> uriBuilder
                .path("/user")
                .queryParam("page", 1)
                .queryParam("size", 10)
                .build())
        .headers(headers -> {
            headers.setBearerAuth(token);
            headers.add("appId", "1001");})
        .retrieve()
        .bodyToMono(User.class)
        .block();

通過(guò) bodyToMono(User.class) Spring 會(huì)自動(dòng) JSON 轉(zhuǎn) User 對(duì)象。

十一、POST 請(qǐng)求示例

請(qǐng)求

POST /user
Content-Type: application/json

請(qǐng)求體:

{
  "name":"張三",
  "password":"123",
}

DTO

@Data
public class UserReq {
    private String name;
    private String password;
}

POST 代碼

UserReq req = new UserReq();
req.setName("張三");
req.setPassword("123");
String token = "Bearer xxxxxx";
String result = webClient.post()
        .uri("/user")
    	//JSON 請(qǐng)求
    	.contentType(MediaType.APPLICATION_JSON)
   		 //單次請(qǐng)求攜帶 Token. 可在配置類(lèi)全局配置 Token
    	.header(HttpHeaders.AUTHORIZATION, token)
        .bodyValue(req)
        .retrieve()
        .bodyToMono(String.class)
        .block();

如果是表單請(qǐng)求:

.contentType(MediaType.APPLICATION_FORM_URLENCODED)

bodyValue() 是什么?

它表示:

把對(duì)象轉(zhuǎn)為請(qǐng)求體 JSON

等價(jià)于:

{
  "name":"張三"
}

十二、PUT 請(qǐng)求

webClient.put()
        .uri("/user/1")
        .bodyValue(req)
        .retrieve()
        .bodyToMono(String.class)
        .block();

十三、DELETE 請(qǐng)求

webClient.delete()
        .uri("/user/1")
        .retrieve()
        .bodyToMono(String.class)
        .block();

十四、下載文件

這是企業(yè)里非常常見(jiàn)的場(chǎng)景。

下載文件為 byte[]

byte[] data = webClient.get()
        .uri("https://example.com/test.pdf")
        //如果需要攜帶token
    	.header(HttpHeaders.AUTHORIZATION,"Bearer xxxxxx")
        .retrieve()
        .bodyToMono(byte[].class)
        .block();

保存本地文件

byte[] data = webClient.get()
        .uri("https://example.com/test.pdf")
    	//如果需要攜帶token
    	.header(HttpHeaders.AUTHORIZATION,"Bearer xxxxxx")
        .retrieve()
        .bodyToMono(byte[].class)
        .block();

Files.write(
        Paths.get("D:/test.pdf"),
        data
);

大文件下載(推薦流式)

如果文件很大, 有幾百 MB 或者 幾 GB,不推薦上面的 byte[] 下載,否則可能 OOM(內(nèi)存溢出)

流式下載

Flux<DataBuffer> flux = webClient.get()
        .uri("/download/file")
        .retrieve()
        .bodyToFlux(DataBuffer.class);
DataBufferUtils.write(
        flux,
        Paths.get("D:/big.zip"),
        StandardOpenOption.CREATE
).block();

或者:

webClient.get()
        .uri("https://example.com/big.zip")
        .retrieve()
        .bodyToFlux(DataBuffer.class)
        .map(DataBuffer::asByteBuffer)
        .doOnNext(buffer -> {
            // 寫(xiě)入文件
        })
        .blockLast();

十五、錯(cuò)誤處理

普通寫(xiě)法

webClient.get()
        .uri("/user")
        .retrieve()
        .bodyToMono(String.class)

如果:

404
500

會(huì)拋異常。

onStatus 狀態(tài)碼錯(cuò)誤處理

String result = webClient.get()
        .uri("/user")
        .retrieve()
        .onStatus(
                HttpStatusCode::is4xxClientError,
                response -> Mono.error(new RuntimeException("4xx異常"))
        )
        .onStatus(
                HttpStatusCode::is5xxServerError,
                response -> Mono.error(new RuntimeException("5xx異常"))
        )
        .bodyToMono(String.class)
        .block();

try-catch

try {
    String result = webClient.get()
            .uri("/test")
            .retrieve()
            .bodyToMono(String.class)
            .block();
} catch (Exception e) {
    e.printStackTrace();
}

十六、retrieve() 和 exchangeToMono() 區(qū)別

retrieve()(最常用)

適合:

  • 普通接口調(diào)用
  • 簡(jiǎn)潔開(kāi)發(fā)

簡(jiǎn)單場(chǎng)景:

.retrieve()
.bodyToMono(...)

exchangeToMono()

適合高級(jí)場(chǎng)景:

  • 獲取狀態(tài)碼
  • 獲取響應(yīng)頭、cookie
  • 自定義響應(yīng)處理
String result = webClient.get()
        .uri("/user")
        .exchangeToMono(response -> {
            if (response.statusCode().is2xxSuccessful()) {
                return response.bodyToMono(String.class);
            }
            return Mono.error(
                    new RuntimeException("請(qǐng)求失敗")
            );
        })
        .block();

十七、 WebClient適合場(chǎng)景與不適合場(chǎng)景?

非常適合:

  • 微服務(wù)
  • 高并發(fā)
  • API 網(wǎng)關(guān)
  • 聚合接口
  • AI 調(diào)用
  • 并發(fā)請(qǐng)求多個(gè)服務(wù)
  • SSE/流式響應(yīng)

不適合的場(chǎng)景:

如果你的項(xiàng)目:

完全同步
低并發(fā)
傳統(tǒng) MVC

那么:

RestTemplate / RestClient

可能更簡(jiǎn)單。

社區(qū)里也有很多開(kāi)發(fā)者提到:

  • WebFlux 會(huì)增加復(fù)雜度
  • Mono / Flux 學(xué)習(xí)成本較高 (Reddit)

十八、WebClient 學(xué)習(xí)路線(xiàn)

建議按這個(gè)順序?qū)W習(xí):

  1. WebClient 基礎(chǔ) API
  2. Mono / Flux
  3. Reactor
  4. 異步編程
  5. 響應(yīng)式編程
  6. Netty
  7. 背壓(BackPressure)

十九、最常用寫(xiě)法總結(jié)

1.GET

webClient.get()

2.POST

webClient.post()

3.設(shè)置 header

.header()

4.設(shè)置 body

.bodyValue()

5.獲取響應(yīng)

.retrieve()
.bodyToMono()

6.阻塞等待

.block()

二十、完整實(shí)戰(zhàn)示例

封裝 HttpClientService

@Service
public class HttpClientService {
    private final WebClient webClient;
    public HttpClientService(WebClient.Builder builder) {
        this.webClient = builder
                .baseUrl("https://api.example.com")
                .defaultHeader(HttpHeaders.CONTENT_TYPE,
                        MediaType.APPLICATION_JSON_VALUE)
                .build();
    }
    // GET
    public String getUser() {
        return webClient.get()
                .uri("/user/1")
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }
    // POST
    public String login(LoginRequest request) {
        return webClient.post()
                .uri("/login")
                .bodyValue(request)
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }
    // token請(qǐng)求
    public String getWithToken(String token) {
        return webClient.get()
                .uri("/user/info")
                .header(HttpHeaders.AUTHORIZATION,
                        "Bearer " + token)
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }
}

二十一、最后總結(jié)

WebClient 本質(zhì)上:

Spring 官方現(xiàn)代 HTTP 客戶(hù)端

它最大的特點(diǎn):

  • 非阻塞
  • 響應(yīng)式
  • 高并發(fā)
  • 異步
  • 鏈?zhǔn)?API

企業(yè)中現(xiàn)在越來(lái)越多:

微服務(wù) + WebClient

的組合。

但它的核心難點(diǎn)其實(shí)不是 WebClient 本身,而是:

Mono / Flux / Reactor

到此這篇關(guān)于SpringBoot WebClient 全面解析的文章就介紹到這了,更多相關(guān)SpringBoot WebClient 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中的回調(diào)機(jī)制使用方式

    Java中的回調(diào)機(jī)制使用方式

    回調(diào)機(jī)制是一種編程模式,允許對(duì)象在特定事件觸發(fā)時(shí)反向調(diào)用調(diào)用方,Java中通過(guò)接口、抽象類(lèi)或Lambda實(shí)現(xiàn),支持同步與異步操作,廣泛用于事件處理、異步編程等場(chǎng)景,具有解耦優(yōu)勢(shì)但也存在回調(diào)地獄等維護(hù)難題
    2025-08-08
  • 關(guān)于java.lang.IncompatibleClassChangeError錯(cuò)誤解決方案

    關(guān)于java.lang.IncompatibleClassChangeError錯(cuò)誤解決方案

    最近開(kāi)發(fā)中遇到類(lèi)沖突報(bào)錯(cuò) java.lang.IncompatibleClassChangeError,所以下面這篇文章主要給大家介紹了關(guān)于java.lang.IncompatibleClassChangeError錯(cuò)誤的解決方案,需要的朋友可以參考下
    2024-02-02
  • Java多線(xiàn)程環(huán)境下使用的集合類(lèi)示例詳解

    Java多線(xiàn)程環(huán)境下使用的集合類(lèi)示例詳解

    這篇文章主要給大家介紹了關(guān)于Java多線(xiàn)程環(huán)境下使用的集合類(lèi)的相關(guān)資料,開(kāi)發(fā)過(guò)程中經(jīng)常遇到這種需求,文中通過(guò)代碼示例和圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Java數(shù)據(jù)結(jié)構(gòu)之二叉排序樹(shù)的實(shí)現(xiàn)

    Java數(shù)據(jù)結(jié)構(gòu)之二叉排序樹(shù)的實(shí)現(xiàn)

    二叉排序樹(shù)(Binary Sort Tree),又稱(chēng)二叉查找樹(shù)(Binary Search Tree),亦稱(chēng)二叉搜索樹(shù)。本文詳細(xì)介紹了二叉排序樹(shù)的原理,并且提供了Java代碼的完全實(shí)現(xiàn)。需要的可以參考一下
    2022-01-01
  • Spring Boot Jar 包部署腳本的實(shí)例講解

    Spring Boot Jar 包部署腳本的實(shí)例講解

    在本篇文章里小編給大家整理的是一篇關(guān)于Spring Boot Jar 包部署腳本的實(shí)例講解內(nèi)容,對(duì)此有興趣的朋友們可以跟著學(xué)習(xí)下。
    2021-12-12
  • 關(guān)于SpringBoot微服務(wù)發(fā)布與部署的三種方式

    關(guān)于SpringBoot微服務(wù)發(fā)布與部署的三種方式

    SpringBoot 框架只提供了一套基于可執(zhí)行 jar 包(executable jar)格式的標(biāo)準(zhǔn)發(fā)布形式,但并沒(méi)有對(duì)部署做過(guò)多的界定,而且為了簡(jiǎn)化可執(zhí)行 jar 包的生成,SpringBoot 提供了相應(yīng)的 Maven 項(xiàng)目插件,需要的朋友可以參考下
    2023-05-05
  • Spring Validation中9個(gè)數(shù)據(jù)校驗(yàn)工具使用指南

    Spring Validation中9個(gè)數(shù)據(jù)校驗(yàn)工具使用指南

    Spring Validation作為Spring生態(tài)系統(tǒng)的重要組成部分,提供了一套強(qiáng)大而靈活的數(shù)據(jù)校驗(yàn)機(jī)制,本文給大家介紹了Spring Validation中9個(gè)數(shù)據(jù)校驗(yàn)工具的使用指南,需要的朋友可以參考下
    2025-05-05
  • Mybatis詳解動(dòng)態(tài)SQL以及單表多表查詢(xún)的應(yīng)用

    Mybatis詳解動(dòng)態(tài)SQL以及單表多表查詢(xún)的應(yīng)用

    MyBatis的動(dòng)態(tài)SQL是基于OGNL表達(dá)式的,它可以幫助我們方便的在SQL語(yǔ)句中實(shí)現(xiàn)某些邏輯,下面這篇文章主要給大家介紹了關(guān)于Mybatis超級(jí)強(qiáng)大的動(dòng)態(tài)SQL語(yǔ)句的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • 解決spring-boot 打成jar包后 啟動(dòng)時(shí)指定參數(shù)無(wú)效的問(wèn)題

    解決spring-boot 打成jar包后 啟動(dòng)時(shí)指定參數(shù)無(wú)效的問(wèn)題

    這篇文章主要介紹了解決spring-boot 打成jar包后 啟動(dòng)時(shí)指定參數(shù)無(wú)效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 使用SpringBoot?+?Vue?+?Redis實(shí)現(xiàn)驗(yàn)證碼登錄功能全過(guò)程

    使用SpringBoot?+?Vue?+?Redis實(shí)現(xiàn)驗(yàn)證碼登錄功能全過(guò)程

    在現(xiàn)代web應(yīng)用中,用戶(hù)驗(yàn)證是非常重要的一部分,這篇文章主要介紹了使用SpringBoot?+?Vue?+?Redis實(shí)現(xiàn)驗(yàn)證碼登錄功能的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-10-10

最新評(píng)論

邻水| 二连浩特市| 遵义市| 白城市| 青阳县| 元阳县| 惠州市| 河曲县| 福鼎市| 龙门县| 渭源县| 抚顺县| 新化县| 富裕县| 凤凰县| 昭通市| 龙游县| 重庆市| 太谷县| 青田县| 扶沟县| 托里县| 衡阳县| 丹寨县| 抚顺县| 云林县| 鹤山市| 安溪县| 竹溪县| 石狮市| 保山市| 延寿县| 大新县| 方正县| 淮南市| 新闻| 龙岩市| 石台县| 射阳县| 五指山市| 嘉定区|