spring boot 3.x 中 webclient 全面详解及示例
1. webclient 简介
- 定义:spring 5 引入的响应式 http 客户端,用于替代
resttemplate(已弃用),支持异步非阻塞的 http 请求。 - 核心特性:
- 支持所有 http 方法(get/post/put/delete 等)。
- 灵活配置请求头、请求体、uri 参数。
- 直接返回
mono<responseentity>或flux获取响应细节。 - 支持链式调用和响应式流处理。
- 依赖:
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-webflux</artifactid> </dependency>
2. 示例代码详解
示例 1:get 请求(带请求头,获取状态码和响应头)
// 1. 创建 webclient 实例
webclient webclient = webclient.builder()
.baseurl("http://api.example.com")
.build();
// 2. 发送 get 请求
mono<responseentity<user>> responsemono = webclient.get()
.uri("/users/{id}", 123) // 路径参数
.header("authorization", "bearer token_123") // 添加请求头
.retrieve() // 开始发送请求
.toentity(user.class); // 转换响应体为 user 对象
// 3. 处理响应
responsemono.block().ifpresent(response -> {
int statuscode = response.getstatuscode().value(); // 状态码
httpheaders headers = response.getheaders(); // 响应头
user user = response.getbody(); // 响应体
});示例 2:post 请求(传递 json 请求体)
// 1. 创建请求体对象
user newuser = new user("john", 25);
// 2. 发送 post 请求
mono<responseentity<string>> responsemono = webclient.post()
.uri("/users")
.contenttype(mediatype.application_json) // 设置 content-type
.bodyvalue(newuser) // 请求体(自动序列化为 json)
.retrieve()
.toentity(string.class); // 返回响应体(如成功返回 "created")
// 3. 处理响应
string locationheader = responsemono.block().getheaders().getfirst("location"); // 获取 location 头示例 3:put/patch 请求(更新资源)
// 1. 更新对象
user updateduser = new user("john doe", 26);
// 2. 发送 put 请求
mono<void> responsemono = webclient.put()
.uri("/users/123")
.contenttype(mediatype.application_json)
.bodyvalue(updateduser)
.retrieve()
.tobodilessentity(); // 无响应体时使用
// 3. 检查状态码
responsemono.block(); // 若无异常,则成功示例 4:delete 请求
mono<void> responsemono = webclient.delete()
.uri("/users/123")
.retrieve()
.tobodilessentity();
// 检查状态码(如 204 no content)
responsemono.block();示例 5:自定义响应类型(如 map)
mono<responseentity<map<string, object>>> responsemono = webclient.get()
.uri("/data")
.retrieve()
.toentity(new parameterizedtypereference<map<string, object>>() {});
map<string, object> data = responsemono.block().getbody();示例 6:使用响应提取器定制返回
// 自定义提取器:提取响应体中的某个字段
mono<string> customheadermono = webclient.get()
.uri("/headers")
.retrieve()
.onstatus(httpstatus::is4xxclienterror,
clientresponse -> mono.error(new runtimeexception("client error")))
.header("x-custom-header") // 直接提取指定头
.switchifempty(mono.just("default"));
string customheader = customheadermono.block();示例 7:批量操作(查询多个资源)
// 1. 构建带查询参数的 uri
mono<user[]> responsemono = webclient.get()
.uri(uribuilder -> uribuilder
.path("/users")
.queryparam("page", 1)
.queryparam("size", 10)
.build())
.retrieve()
.bodytomono(user[].class); // 返回数组
user[] users = responsemono.block();3. 核心方法对比表格
| 方法 | http 方法 | 返回类型 | 关键代码片段 | 适用场景 |
|---|---|---|---|---|
get() | get | mono<user> | webclient.get().uri("/users/1").retrieve().bodytomono(user.class); | 简单 get 请求,直接返回对象 |
retrieve().toentity() | get | mono<responseentity<user>> | webclient.get().uri("/users/1").retrieve().toentity(user.class); | 需获取状态码或响应头 |
post().bodyvalue() | post | mono<string> | webclient.post().bodyvalue(newuser).retrieve().bodytomono(string.class); | 发送 json 请求体,直接返回结果 |
put().retrieve().tobodilessentity() | put | mono<void> | webclient.put().uri("/users/1").retrieve().tobodilessentity(); | 更新资源,无响应体 |
delete() | delete | mono<void> | webclient.delete().uri("/users/1").retrieve().tobodilessentity(); | 删除资源 |
4. 关键配置与注意事项
设置超时:
webclient webclient = webclient.builder() .timeout(duration.ofseconds(5)) .build();异常处理:
mono<user> response = webclient.get() .uri("/users/invalid") .retrieve() .onstatus(httpstatus::is4xxclienterror, clientresponse -> mono.error(new customexception())) .bodytomono(user.class);自定义序列化:
objectmapper objectmapper = new objectmapper(); webclient webclient = webclient.builder() .codecs(configurer -> configurer.defaultcodecs() .jackson2jsonencoder(new jackson2jsonencoder(objectmapper))) .build();
5. 总结对比表格
| 需求 | 实现方法 | 关键代码 | 注意事项 |
|---|---|---|---|
| 发送 json 请求体 | 使用 bodyvalue() 或 body(bodyinserter) | .contenttype(mediatype.application_json).bodyvalue(newuser); | 确保序列化配置正确 |
| 获取状态码和响应头 | 返回 responseentity | .retrieve().toentity(user.class) | 处理 2xx/4xx/5xx 状态码 |
| 自定义响应类型 | 使用 parameterizedtypereference 或泛型 | .bodytomono(new parameterizedtypereference<list<user>>() {}) | 处理复杂泛型类型 |
| 响应提取器定制 | 使用 .header()、.bodytomono() 或自定义转换逻辑 | .header("x-custom-header").switchifempty(mono.just("default")); | 简化复杂响应处理逻辑 |
关键总结
- 核心类:
webclient:核心客户端,支持链式调用。mono/flux:响应式类型,处理异步响应。responseentity:封装响应头、状态码和体。
- 最佳实践:
- 使用
retrieve()统一处理响应。 - 通过
.onstatus()处理异常状态码。 - 自定义
codecs配置序列化器。
- 使用
- 响应式特性:
- 非阻塞 i/o,适合高并发场景。
- 需用
block()或subscribe()处理异步结果(生产环境建议用非阻塞方式)。
通过以上示例和配置,开发者可以高效实现 rest api 的全场景调用需求,充分利用 spring webflux 的响应式优势。
到此这篇关于spring boot 3.x 中 webclient 全面详解及示例的文章就介绍到这了,更多相关springboot webclient内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论