网站首页 > 文章精选 正文
WebClient 是 Spring WebFlux 提供的一个非阻塞、响应式的 HTTP 客户端,用于替代传统的同步阻塞式客户端 RestTemplate。它是构建现代响应式微服务调用链的重要工具,适用于需要高性能、异步请求处理的场景。
一、什么是 WebClient?
- 非阻塞 I/O:基于 Reactor 的 Mono 和 Flux,支持异步请求。
- 函数式编程风格:使用链式调用方式编写清晰易读的代码。
- 支持多种数据格式:JSON、XML、表单、流等。
- 可扩展性强:支持拦截器、编码解码器、自定义过滤器等。
- 与 Spring 生态集成良好:Spring Boot、Spring Security、R2DBC 等。
二、基本使用示例
1. 创建 WebClient 实例
WebClient webClient = WebClient.create("https://api.example.com");
也可以使用 builder 模式创建更复杂的配置:
WebClient webClient = WebClient.builder()
.baseUrl("https://api.example.com")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
2. GET 请求获取资源
Mono<User> userMono = webClient.get()
.uri("/users/{id}", 1)
.retrieve()
.bodyToMono(User.class);
userMono.subscribe(user -> System.out.println("User: " + user.getName()));
3. POST 请求提交数据
User newUser = new User("John", 30);
Mono<User> response = webClient.post()
.uri("/users")
.bodyValue(newUser)
.retrieve()
.bodyToMono(User.class);
response.subscribe(user -> System.out.println("Created user ID: " + user.getId()));
4. 处理错误(异常处理)
可以通过 .onStatus() 来捕获特定状态码的错误,并进行处理:
webClient.get()
.uri("/users/999")
.retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse -> {
return Mono.error(new RuntimeException("Client error"));
})
.onStatus(HttpStatus::is5xxServerError, clientResponse -> {
return Mono.error(new RuntimeException("Server error"));
})
.bodyToMono(User.class)
.subscribe(
user -> System.out.println("User: " + user.getName()),
err -> System.err.println("Error occurred: " + err.getMessage())
);
5. 获取 Flux 流式数据
如果接口返回的是多个对象(如数组或集合),可以使用 Flux<T> 接收:
Flux<User> usersFlux = webClient.get()
.uri("/users")
.retrieve()
.bodyToFlux(User.class);
usersFlux.subscribe(user -> System.out.println("User: " + user.getName()));
三、高级功能
1. 设置超时时间
可以通过配置底层的 ReactorResourceFactory 或直接使用 Netty 配置:
HttpClient httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.doOnConnected(conn -> conn
.addHandlerLast(new ReadTimeoutHandler(5))
.addHandlerLast(new WriteTimeoutHandler(5)));
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
2. 添加过滤器(拦截器)
WebClient webClient = WebClient.builder()
.baseUrl("https://api.example.com")
.filter((request, next) -> {
ClientRequest newRequest = ClientRequest.from(request)
.header("X-API-Key", "your-secret-key")
.build();
return next.exchange(newRequest);
})
.build();
3. 使用 ExchangeFunction 自定义逻辑
ExchangeFunction 可以完全控制请求和响应过程:
ExchangeFunction exchangeFunction = (request, clientResponse) -> {
// 自定义逻辑
return ExchangeFunctions.createDefault().exchange(request, clientResponse);
};
WebClient webClient = WebClient.builder()
.exchangeFunction(exchangeFunction)
.build();
四、WebClient vs RestTemplate
特性 | RestTemplate | WebClient |
是否非阻塞 | 否(同步) | 是(异步) |
响应式编程支持 | 不支持 | 支持(Mono/Flux) |
函数式风格 | 否 | 是 |
性能 | 一般 | 更高(适合高并发) |
是否推荐新项目使用 | 已废弃 | 推荐 |
五、最佳实践建议
- 避免阻塞操作:不要在 WebClient 调用后立即调用 .block(),除非你确实需要等待结果。
- 合理设置超时:网络调用要设置合理的连接和读写超时时间。
- 统一异常处理:使用 .onStatus() 统一处理错误响应。
- 复用 WebClient 实例:一个应用中通常只需要一个或少数几个 WebClient 实例。
- 结合重试机制:可以配合 Resilience4j、Retryable、Spring Retry 等实现自动重试。
六、常见问题
Q:什么时候应该使用 WebClient?
- 在 Spring WebFlux 项目中
- 需要异步非阻塞调用
- 需要处理大量并发请求
- 需要流式数据处理(如 SSE)
- 微服务间通信(尤其是网关层)
Q:WebClient 如何调试?
可以在请求中添加日志打印:
.filter((req, next) -> {
System.out.println("Request: " + req.method() + " " + req.url());
return next.exchange(req);
})
总结:
WebClient 是 Spring WebFlux 中用于发起非阻塞、响应式 HTTP 请求的核心组件,是现代 Spring 应用中进行服务调用的最佳选择。
猜你喜欢
- 2025-07-27 HTTP状态码滥用指南:全栈开发者的REST API最佳实践
- 2025-07-27 开发者必须了解的HTTP头部(http头部参数)
- 2025-07-27 轻松操控C#下载文件:WebClient与HttpClient实战详解
- 2025-07-27 http状态码完整版,再也不需要度娘了。
- 2025-07-27 探索Apache HttpClient超时时间如何设定?
- 2025-07-27 Java实现调用HTTP请求的几种常见方式
- 2025-07-27 HTTP与HTTPS的区别(http和https之间的区别)
- 2025-07-27 100个Java工具类之6:用4种方式发起HTTP请求
- 2025-07-27 HTTP和HTTPS(HTTP和HTTPS的主要区别是什么)
- 2025-07-27 http常见状态码(http常见状态码的含义)
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)
- fmt.println (52)