SpringBoot WebClient 全面解析

 更新时间:2026年05月25日 09:51:32   作者:西凉的悲伤  
WebClient是Spring5非阻塞响应式HTTP客户端,适用于高并发场景和微服务通信,替代RestTemplate更推荐新项目,支持异步并发请求和链式API风格,这篇文章给大家介绍SpringBoot WebClient全面解析,感兴趣的朋友一起看看吧

一、什么是 WebClient?

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

WebClient 它底层基于:

  • Reactor
  • Netty
  • NIO

因此:

少量线程
处理大量请求

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

官方文档:

二、 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 最简单的使用方式

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 配置类方式(推荐)

配置类

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

通常 token 是动态获取的,可以使用 filter,下面的示例使用 getToken() 动态获取 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 配置项包括:

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

注入使用

@Autowired
private WebClient webClient;

九、GET 带参数

请求

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

最终请求:

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 类

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

调用

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

如果带参数和请求头:

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

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

十一、POST 请求示例

请求

POST /user
Content-Type: application/json

请求体:

{
  "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 请求
    	.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 状态码错误处理

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() 区别

retrieve()(最常用)

适合:

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

简单场景:

.retrieve()
.bodyToMono(...)

exchangeToMono()

适合高级场景:

  • 获取状态码
  • 获取响应头、cookie
  • 自定义响应处理
String result = webClient.get()
        .uri("/user")
        .exchangeToMono(response -> {
            if (response.statusCode().is2xxSuccessful()) {
                return response.bodyToMono(String.class);
            }
            return Mono.error(
                    new RuntimeException("请求失败")
            );
        })
        .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

@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请求
    public String getWithToken(String token) {
        return webClient.get()
                .uri("/user/info")
                .header(HttpHeaders.AUTHORIZATION,
                        "Bearer " + token)
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }
}

二十一、最后总结

WebClient 本质上:

Spring 官方现代 HTTP 客户端

它最大的特点:

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

企业中现在越来越多:

微服务 + WebClient

的组合。

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

Mono / Flux / Reactor

到此这篇关于SpringBoot WebClient 全面解析的文章就介绍到这了,更多相关SpringBoot WebClient 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot和Hazelcast使用详解

    Spring Boot和Hazelcast使用详解

    这篇文章主要介绍了Spring Boot和Hazelcast使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • SpringBoot自动装配之@Import深入讲解

    SpringBoot自动装配之@Import深入讲解

    由于最近的项目需求,需要在把配置类导入到容器中,通过查询,使用@Import注解就能实现这个功能,@Import注解能够帮我们吧普通配置类(定义为Bean的类)导入到IOC容器中
    2023-01-01
  • SpringBoot+Vue简单前后端分离项目的增删改查方式

    SpringBoot+Vue简单前后端分离项目的增删改查方式

    文章主要介绍了使用SpringBoot进行前后端开发的过程,包括SpringBoot项目的搭建、配置、后端业务开发、前端页面搭建等步骤,并详细阐述了数据增删改查的实现方法
    2026-04-04
  • Java泛型最全知识总结

    Java泛型最全知识总结

    面试被问到Java泛型怎么办,有了这篇文章,让你直接保送,文中有非常详细的知识总结及相关代码示例,需要的朋友可以参考下
    2021-06-06
  • 深入了解volatile和Java内存模型

    深入了解volatile和Java内存模型

    在本篇文章当中,主要给大家深入介绍Volatile关键字和Java内存模型。在文章当中首先先介绍volatile的作用和Java内存模型,然后层层递进介绍实现这些的具体原理、JVM底层是如何实现volatile的和JVM实现的汇编代码以及CPU内部结构,感兴趣的可以了解一下
    2022-08-08
  • SpringBoot接收参数所有方式总结

    SpringBoot接收参数所有方式总结

    这篇文章主要介绍了SpringBoot接收参数所有方式总结,文中通过代码示例和图文结合的方式给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-07-07
  • java中的基础运算符

    java中的基础运算符

    这篇文章主要介绍了Java基本数据类型和运算符,结合实例形式详细分析了java基本数据类型、数据类型转换、算术运算符、逻辑运算符等相关原理与操作技巧,需要的朋友可以参考下
    2021-08-08
  • JAVA WSIMPORT生成WEBSERVICE客户端401认证过程图解

    JAVA WSIMPORT生成WEBSERVICE客户端401认证过程图解

    这篇文章主要介绍了JAVA WSIMPORT生成WEBSERVICE客户端401认证过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • SpringBoot整合Spring Data JPA的详细方法

    SpringBoot整合Spring Data JPA的详细方法

    JPA全称为Java Persistence API(Java持久层API),是一个基于ORM的标准规范,在这个规范中,JPA只定义标准规则,不提供实现,本文重点给大家介绍SpringBoot整合Spring Data JPA的相关知识,感兴趣的朋友一起看看吧
    2022-02-02
  • Java 多态从原理到实践的深度解析

    Java 多态从原理到实践的深度解析

    本文将从多态的定义出发,逐层拆解其实现原理、分类、实战案例,帮你彻底掌握Java多态的核心知识,本文通过案例给大家讲解的非常详细,感兴趣的朋友跟随小编一起看看吧
    2026-02-02

最新评论