SpringBoot WebClient 介绍
2026/5/25 15:43:36 网站建设 项目流程

目录

  • 一、什么是 WebClient?
  • 二、 WebClient 能解决什么问题?
  • 三、WebClient 和 RestTemplate 的区别
  • 四、WebClient 的核心优势
    • 1. 非阻塞(Non-Blocking)
    • 2. 支持异步
    • 3. 链式 API 更现代
  • 五、WebClient 的核心对象
  • 六、Mono 和 Flux 是什么?
  • 七、如何引入 WebClient?
    • Maven
  • 八、WebClient 的基本创建方式
    • 1. 创建 WebClient 最简单的使用方式
    • 2.Spring Bean 配置类方式(推荐)
  • 九、GET 带参数
    • 请求
    • 代码
    • 代码解析
      • get()
      • uri()
      • headers()
      • retrieve()
      • bodyToMono()
      • block()
  • 十、GET 返回对象
    • User 类
    • 调用
  • 十一、POST 请求示例
    • 请求
    • DTO
    • POST 代码
    • bodyValue() 是什么?
  • 十二、PUT 请求
  • 十三、DELETE 请求
  • 十四、下载文件
    • 下载文件为 byte[]
    • 保存本地文件
    • 大文件下载(推荐流式)
  • 十五、错误处理
    • 普通写法
    • onStatus 状态码错误处理
    • try-catch
  • 十六、retrieve() 和 exchangeToMono() 区别
    • retrieve()(最常用)
    • exchangeToMono()
  • 十七、 WebClient适合场景与不适合场景?
  • 十八、WebClient 学习路线
  • 十九、最常用写法总结
    • 1.GET
    • 2.POST
    • 3.设置 header
    • 4.设置 body
    • 5.获取响应
    • 6.阻塞等待
  • 二十、完整实战示例
  • 二十一、最后总结

一、什么是 WebClient?

WebClient是 Spring 5 引入的一个现代 HTTP 客户端,属于 Spring WebFlux 模块,用来发送 HTTP 请求(GET、POST、PUT、DELETE 等)。
它可以替代传统的RestTemplate。(Home)

WebClient 它底层基于:

  • Reactor
  • Netty
  • NIO

因此:

少量线程 处理大量请求

这也是它高并发能力强的原因。(Home)

官方文档:

  • Spring WebClient 官方文档
  • Spring WebFlux 官方文档

二、 WebClient 能解决什么问题?

它主要用于:

  • 调用第三方接口
  • 微服务之间通信
  • 下载文件
  • 上传文件
  • 调用 AI / OpenAPI 接口
  • 高并发 HTTP 请求
  • 异步并发调用多个接口

例如:

你的系统 ↓ WebClient ↓ 支付宝接口 / 微信接口 / 第三方系统

三、WebClient 和 RestTemplate 的区别

对比项WebClientRestTemplate
所属Spring WebFluxSpring MVC
是否异步支持默认同步阻塞
是否非阻塞
是否支持响应式支持 Mono / Flux不支持
并发能力一般
是否支持流式处理支持一般
推荐程度新项目推荐维护模式
API 风格链式 fluent API模板式 API

Spring 官方已经说明:

  • RestTemplate进入 maintenance mode(维护模式)
  • 新项目更推荐WebClient(Reddit)

四、WebClient 的核心优势

1. 非阻塞(Non-Blocking)

传统 RestTemplate:

线程发请求 ↓ 一直等待响应 ↓ 线程被占用

WebClient:

线程发请求 ↓ 不用等待 ↓ 线程去处理别的任务 ↓ 响应回来再通知

因此:

  • 更省线程
  • 更适合高并发
  • 更适合微服务

支持同步调用

WebClient 虽然是响应式的,但你也能:

.block()

变成同步调用。

因此:

即使你不是响应式项目,也能使用 WebClient。


2. 支持异步

可以同时请求多个接口:

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

最后组合:

Mono.zip(userMono,orderMono)

3. 链式 API 更现代

传统的 RestTemplate:

restTemplate.exchange(...)

而 WebClient:

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

更像:

  • Java8 Stream
  • 函数式编程
  • Reactor 响应式风格

五、WebClient 的核心对象

最重要的:

WebClient

它类似:

浏览器客户端

负责:

  • 发请求
  • 设置 header
  • 设置 token
  • 接收响应
  • 下载文件

六、Mono 和 Flux 是什么?

WebClient 基于 Reactor。

两个核心类:

类型含义
Mono0~1 个结果
Flux0~N 个结果

例如:

Mono<User>Flux<User>

表示:

Mono<User>表示未来会返回一个 User Flux<User>表示未来会返回多个 User

七、如何引入 WebClient?

Maven

Spring Boot 项目:

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

即使你项目不是 WebFlux 项目,也能单独使用 WebClient。


八、WebClient 的基本创建方式

1. 创建 WebClient 最简单的使用方式

WebClientwebClient=WebClient.create();

或者:

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

或者:

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

2.Spring Bean 配置类方式(推荐)

配置类

@ConfigurationpublicclassWebClientConfig{@BeanpublicWebClientwebClient(){//配置超时和日志HttpClienthttpClient=HttpClient.create().responseTimeout(Duration.ofSeconds(10)).wiretap(true);returnWebClient.builder()//基本url域名.baseUrl("https://api.example.com")//默认请求头增加类型为json.defaultHeader(HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_JSON_VALUE)//默认请求头增加token.defaultHeader(HttpHeaders.AUTHORIZATION,"Bearer abcdefg")//超时配置和日志.clientConnector(newReactorClientHttpConnector(httpClient)).build();}}

通常 token 是动态获取的,可以使用 filter,下面的示例使用 getToken() 动态获取 token。

Filter 示例

@BeanpublicWebClientwebClient(){returnWebClient.builder().filter((request,next)->{ClientRequestnewRequest=ClientRequest.from(request).header(HttpHeaders.AUTHORIZATION,"Bearer "+getToken()).build();returnnext.exchange(newRequest);}).build();}

官方 builder 配置项包括:

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

注入使用

@AutowiredprivateWebClientwebClient;

九、GET 带参数

请求

GET /user?page=1&size=10

代码

Stringresult=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();

最终请求:

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

代码解析

get()

表示 GET 请求:

webClient.get()

uri()

请求地址。

如果请求地址很简单可以这样写:

.uri("/user")

headers()

增加请求头,可以在配置类里配置默认的请求头


retrieve()

开始发送请求并获取响应:

.retrieve()

bodyToMono()

响应转对象:

.bodyToMono(String.class)

block()

阻塞等待结果:

.block();

注意:

WebClient 本身是异步的。

调用:

.block()

才会变成同步等待。


十、GET 返回对象

User 类

@DatapublicclassUser{privateLongid;privateStringname;}

调用

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

如果带参数和请求头:

Useruser=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();

通过 bodyToMono(User.class) Spring 会自动 JSON 转 User 对象。


十一、POST 请求示例

请求

POST /user Content-Type: application/json

请求体:

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

DTO

@DatapublicclassUserReq{privateStringname;privateStringpassword;}

POST 代码

UserReqreq=newUserReq();req.setName("张三");req.setPassword("123");Stringtoken="Bearer xxxxxx";Stringresult=webClient.post().uri("/user")//JSON 请求.contentType(MediaType.APPLICATION_JSON)//单次请求携带 Token. 可在配置类全局配置 Token.header(HttpHeaders.AUTHORIZATION,token).bodyValue(req).retrieve().bodyToMono(String.class).block();

如果是表单请求:

.contentType(MediaType.APPLICATION_FORM_URLENCODED)

bodyValue() 是什么?

它表示:

把对象转为请求体 JSON

等价于:

{"name":"张三"}

十二、PUT 请求

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

十三、DELETE 请求

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

十四、下载文件

这是企业里非常常见的场景。


下载文件为 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(内存溢出)

流式下载

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->{// 写入文件}).blockLast();

十五、错误处理

普通写法

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

如果:

404 500

会抛异常。


onStatus 状态码错误处理

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

try-catch

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

十六、retrieve() 和 exchangeToMono() 区别

retrieve()(最常用)

适合:

  • 普通接口调用
  • 简洁开发

简单场景:

.retrieve().bodyToMono(...)

exchangeToMono()

适合高级场景:

  • 获取状态码
  • 获取响应头、cookie
  • 自定义响应处理
Stringresult=webClient.get().uri("/user").exchangeToMono(response->{if(response.statusCode().is2xxSuccessful()){returnresponse.bodyToMono(String.class);}returnMono.error(newRuntimeException("请求失败"));}).block();

十七、 WebClient适合场景与不适合场景?

非常适合:

  • 微服务
  • 高并发
  • API 网关
  • 聚合接口
  • AI 调用
  • 并发请求多个服务
  • SSE/流式响应

不适合的场景:

如果你的项目:

完全同步 低并发 传统 MVC

那么:

RestTemplate / RestClient

可能更简单。

社区里也有很多开发者提到:

  • WebFlux 会增加复杂度
  • Mono / Flux 学习成本较高 (Reddit)

十八、WebClient 学习路线

建议按这个顺序学习:

  1. WebClient 基础 API
  2. Mono / Flux
  3. Reactor
  4. 异步编程
  5. 响应式编程
  6. Netty
  7. 背压(BackPressure)

十九、最常用写法总结

1.GET

webClient.get()

2.POST

webClient.post()

3.设置 header

.header()

4.设置 body

.bodyValue()

5.获取响应

.retrieve().bodyToMono()

6.阻塞等待

.block()

二十、完整实战示例

封装 HttpClientService

@ServicepublicclassHttpClientService{privatefinalWebClientwebClient;publicHttpClientService(WebClient.Builderbuilder){this.webClient=builder.baseUrl("https://api.example.com").defaultHeader(HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_JSON_VALUE).build();}// GETpublicStringgetUser(){returnwebClient.get().uri("/user/1").retrieve().bodyToMono(String.class).block();}// POSTpublicStringlogin(LoginRequestrequest){returnwebClient.post().uri("/login").bodyValue(request).retrieve().bodyToMono(String.class).block();}// token请求publicStringgetWithToken(Stringtoken){returnwebClient.get().uri("/user/info").header(HttpHeaders.AUTHORIZATION,"Bearer "+token).retrieve().bodyToMono(String.class).block();}}

二十一、最后总结

WebClient 本质上:

Spring 官方现代 HTTP 客户端

它最大的特点:

  • 非阻塞
  • 响应式
  • 高并发
  • 异步
  • 链式 API

企业中现在越来越多:

微服务 + WebClient

的组合。

但它的核心难点其实不是 WebClient 本身,而是:

Mono / Flux / Reactor

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询