WebClient 简述

2025-12-12 0 805

一、介绍

1、WebClient 是什么?

  • 定义:Spring 5 引入的响应式 HTTP 客户端,位于 spring-webflux 模块
  • 作用:替代老旧的 RestTemplate(Spring 6 起 RestTemplate 已处于“维护模式”)
  • 编程风格:Reactive(Reactor Flux / Mono),也支持同步阻塞调用
  • 底层:Netty(默认),也可切换为 Jetty Reactor、Apache HttpComponents 等

2、为什么选 WebClient?

  • 响应式:高并发、少线程、低延迟,在 IO 密集场景下的 QPS 更高,同步阻塞场景也能用
  • 流式 API:链式调用,天然可组合 retrytimeoutfilter 等,代码更短、更直观
  • 协议全覆盖:封装 HTTP/1.1、HTTP/2、WebSocket、SSE 等多种协议
  • 无缝集成:Spring Cloud、Spring Security、Spring Data R2DBC 等全家桶链路生态

二、使用方法

1、引入依赖

正如前文所言,WebClient 位于 spring-webflux 模块,因此只要 webflux starter 即可。

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

2、创建 WebClient 客户端实例

(1)全局共享

写一个配置类,把 WebClient 注册成单例 Bean。整个应用只需创建一次,任何地方都可以直接 @Autowired 拿来用,这样既省资源又方便统一配置。配置类的代码示例如下:

@Configuration
public class WebClientConfig {

    @Bean                     // 全局唯一实例,Spring 会把该对象放进容器,任何地方都能注入
    public WebClient webClient() {
        return WebClient.builder()
                .baseUrl(\"https://httpbin.org\")   // 公共前缀,可省
                .defaultHeader(HttpHeaders.USER_AGENT, \"demo-app/1.0\")
                .build();
    }
}

(2)临时创建

在代码里手动创建一个 WebClient 实例,不交给 Spring 容器托管,也不共享,代码示例如下:

WebClient client = WebClient.create(\"https://httpbin.org\");

(3)资源管理

  • 全局共享(@Bean)的 WebClient,在 Spring 容器关闭时会连带清理,无需手动关闭
  • 临时创建的 WebClient 用完即丢,也无需手动关闭

3、发送请求

(1)GET(阻塞式)

当前线程会卡住,直到获取响应结果。

String body = client.get()
        .uri(\"/get?name=Tom\")
        .retrieve()
        .bodyToMono(String.class)
        .block();          // 阻塞点
        
System.out.println(\"阻塞结果 = \" + body);

(2)GET(异步回调)

当前线程执行 subscribe 后就可以去做别的事,获取响应结果后回调执行后续逻辑。

client.get()
      .uri(\"/get?name=Jerry\")
      .retrieve()
      .bodyToMono(String.class)
      .subscribe(
              json -> System.out.println(\"异步回调 = \" + json),   // 成功
              err  -> err.printStackTrace()                      // 失败
      );
      
System.out.println(\"主线程继续执行,不等待\");

(3)GET(流式)

适用于服务端持续推送数据的场景,如 SSE、大文件、日志流。这里演示 HTTP 长连接 + 无限行 JSON 的流式消费,代码示例如下:

// 假定 httpbin.org 的 /stream/{n} 会一次返回 n 行 JSON
Flux flux = client.get()
        .uri(\"/stream/10\")          // 10 行数据
        .retrieve()
        .bodyToFlux(String.class);  // 每收到一行就往下游发

flux.doOnNext(line -> System.out.println(\"收到流 => \" + line))
    .subscribe();

(4)POST JSON

把 Java 对象序列化成 JSON 发给服务器。.bodyValue() 会将常见类型自动序列化,如 POJO、基本类型、Map、List 和任意 Collection。

Mono resp = client.post()
        .uri(\"/post\")
        .contentType(MediaType.APPLICATION_JSON)
        .bodyValue(new User(\"Tom\", 18))     // 自动序列化成 JSON
        .retrieve()
        .bodyToMono(String.class);

resp.subscribe(json -> System.out.println(\"POST-JSON 返回 => \" + json));

(5)POST multipart/form-data

这样可以同时上传文件 + 文本,代码示例如下:

// 1. 准备 multipart 主体
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part(\"file\", new FileSystemResource(\"demo.txt\"));  // 文件
builder.part(\"desc\", \"这是说明文字\");                       // 普通字段

// 2. 发送请求
Mono resp = client.post()
        .uri(\"/post\")
        .contentType(MediaType.MULTIPART_FORM_DATA)
        .body(BodyInserters.fromMultipartData(builder.build()))
        .retrieve()
        .bodyToMono(String.class);

resp.subscribe(json -> System.out.println(\"POST-Multipart 返回 => \" + json));

4、语法解释

下面对 WebClient 链式调用里最常见的 5 个方法进行解释:

(1)uri

uri(String path, Object... vars) 是剩余路径,每次请求都可变,会自动拼在前缀 baseUrl 的后面,最终 URL = baseUrl + uri。代码示例如下:

.uri(\"/user/{id}\", 123)   // -> /user/123

(2)retrieve

retrieve() 是一个无参方法,负责把请求发出去 并拿到完整的 HTTP 响应。默认 4xx/5xx 会抛 WebClientResponseException,如果想自己处理错误,需要使用 exchangeToMono 或 onStatus。

(3)bodyToMono

bodyToMono(Class clazz) 会将整个响应体一次性转换成单个对象(Mono),代码示例如下:

.bodyToMono(User.class)     // JSON -> User 对象
.bodyToMono(String.class)   // 原始文本

(4)bodyToFlux

bodyToFlux(Class clazz) 会将持续流切成多个对象(Flux),如SSE、大文件分块等场景,代码示例如下:

.bodyToFlux(String.class);   // 每收到一行就变成一个 String

(5)subscribe

subscribe(Consumer onNext, Consumer onError) 会执行整个链式调用,并提供收到数据/出错时的回调。如果不调用 subscribe() 或 block(),整个链式调用不会真正执行。

.subscribe(
    user -> log.info(\"收到用户 {}\", user),
    ex   -> log.error(\"请求失败\", ex)
)

三、剩余的问题

因为懒惰和大大小小的事情,这一篇拖了很久,久到我都忘记了。以下是剩余的问题,原本是拟定作为一级标题进行学习的,只有暂且搁置,以后有机会再进行补习。

  • 什么是响应式?
  • 什么是 Content-Type?
  • 什么是 Mono?
  • 什么是 Flux?

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 WebClient 简述 https://www.zuozi.net/35739.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务