首页 教程 Web前端 重学SpringBoot3-WebClient配置与使用详解

重学SpringBoot3-WebClient配置与使用详解

更多SpringBoot3内容请关注我的专栏:《SpringBoot3》
期待您的点赞👍收藏⭐评论✍

重学SpringBoot3-WebClient配置与使用详解

  • 1. 简介
  • 2. 环境准备
    • 2.1 依赖配置
  • 3. WebClient配置
    • 3.1 基础配置
    • 3.2 高级配置
    • 3.3 retrieve()和exchange()区别
  • 4. 使用示例
    • 4.1 基本请求操作
    • 4.2 处理复杂响应
    • 4.3 高级用法
  • 5. 最佳实践
  • 6. 注意事项
  • 7. 与RestTemplate对比
  • 8. 总结
  • 参考资料

1. 简介

WebClient是Spring 5引入的响应式Web客户端,用于执行HTTP请求。相比传统的RestTemplate,WebClient提供了非阻塞、响应式的方式来处理HTTP请求,是Spring推荐的新一代HTTP客户端工具。本文将详细介绍如何在SpringBoot 3.x中配置和使用WebClient。

2. 环境准备

2.1 依赖配置

pom.xml中添加必要的依赖:

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.10</version><relativePath/><!-- lookup parent from repository --></parent><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>

3. WebClient配置

3.1 基础配置

@ConfigurationpublicclassWebClientConfig{@BeanpublicWebClientwebClient(){returnWebClient.builder().baseUrl("https://echo.apifox.com").defaultHeader(HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_JSON_VALUE).defaultHeader(HttpHeaders.ACCEPT,MediaType.APPLICATION_JSON_VALUE).build();}}

3.2 高级配置

packagecom.coderjia.boot3webflux.config;importio.netty.channel.ChannelOption;importio.netty.handler.timeout.ReadTimeoutHandler;importio.netty.handler.timeout.WriteTimeoutHandler;importlombok.extern.slf4j.Slf4j;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.http.HttpHeaders;importorg.springframework.http.MediaType;importorg.springframework.http.client.reactive.ReactorClientHttpConnector;importorg.springframework.web.reactive.function.client.ExchangeFilterFunction;importorg.springframework.web.reactive.function.client.WebClient;importreactor.core.publisher.Mono;importreactor.netty.http.client.HttpClient;importreactor.netty.resources.ConnectionProvider;importjava.time.Duration;/** * @author CoderJia * @create 2024/12/3 下午 09:42 * @Description **/@Slf4j@ConfigurationpublicclassWebClientConfig{@BeanpublicWebClientwebClient(){// 配置HTTP连接池ConnectionProvider provider =ConnectionProvider.builder("custom").maxConnections(500).maxIdleTime(Duration.ofSeconds(20)).build();// 配置HTTP客户端HttpClient httpClient =HttpClient.create(provider).option(ChannelOption.CONNECT_TIMEOUT_MILLIS,5000).responseTimeout(Duration.ofSeconds(5)).doOnConnected(conn -> conn.addHandlerLast(newReadTimeoutHandler(5)).addHandlerLast(newWriteTimeoutHandler(5)));// 构建WebClient实例returnWebClient.builder().clientConnector(newReactorClientHttpConnector(httpClient)).baseUrl("https://echo.apifox.com").defaultHeader(HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_JSON_VALUE).defaultHeader(HttpHeaders.ACCEPT,MediaType.APPLICATION_JSON_VALUE)// 添加请求日志记录功能.filter(ExchangeFilterFunction.ofRequestProcessor( clientRequest ->{ log.debug("Request: {} {}", clientRequest.method(), clientRequest.url());returnMono.just(clientRequest);}))// 添加响应日志记录功能.filter(ExchangeFilterFunction.ofResponseProcessor( clientResponse ->{ log.debug("Response status: {}", clientResponse.statusCode());returnMono.just(clientResponse);})).build();}}

3.3 retrieve()和exchange()区别

在使用 WebClient 进行 HTTP 请求时,retrieve() 和 exchange() 方法都可以用来处理响应,但它们有不同的用途和行为。以下是它们的主要区别:
retrieve()

  • 用途:retrieve() 方法用于简化响应处理,特别是当你只需要响应体时。
  • 自动错误处理:retrieve() 会自动处理 HTTP 错误状态码(例如 4xx 和 5xx),并抛出 WebClientResponseException 及其子类。
  • 返回值:通常用于直接获取响应体,例如 bodyToMono(String.class) 或 bodyToFlux(String.class)。
  • 适用场景:适用于大多数常见的请求处理场景,特别是当你不需要手动处理响应状态码时。

exchange()

  • 用途:exchange() 方法提供了更底层的控制,允许你手动处理响应,包括响应状态码和响应头。
  • 手动错误处理:exchange() 不会自动处理 HTTP 错误状态码,你需要手动检查响应状态码并进行相应的处理。
  • 返回值:返回 ClientResponse 对象,你可以从中提取响应状态码、响应头和响应体。
  • 适用场景:适用于需要手动处理响应状态码或响应头的复杂场景。

示例对比

retrieve()

publicMono<JSONObject>get(String q1){return webClient.get().uri(uriBuilder -> uriBuilder .path("/get").queryParam("q1", q1).build()).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(JSONObject.class);}

exchange()

publicMono<JSONObject>get(String q1){return webClient.get().uri(uriBuilder -> uriBuilder .path("/get").queryParam("q1", q1).build()).accept(MediaType.APPLICATION_JSON).exchangeToMono(response ->{if(response.statusCode().is2xxSuccessful()){return response.bodyToMono(JSONObject.class);}else{returnMono.error(newRuntimeException("Request failed with status code: "+ response.statusCode()));}});}

4. 使用示例

4.1 基本请求操作

packagecom.coderjia.boot3webflux.service;importcom.alibaba.fastjson.JSONObject;importjakarta.annotation.Resource;importorg.springframework.http.MediaType;importorg.springframework.stereotype.Service;importorg.springframework.web.reactive.function.client.WebClient;importreactor.core.publisher.Mono;/** * @author CoderJia * @create 2024/12/3 下午 10:22 * @Description **/@ServicepublicclassApiService{@ResourceprivateWebClient webClient;// GET请求publicMono<JSONObject>get(String q1){return webClient.get().uri(uriBuilder -> uriBuilder .path("/get").queryParam("q1", q1).build()).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(JSONObject.class);}// POST请求publicMono<JSONObject>post(JSONObject body){return webClient.post().uri("/post").bodyValue(body).retrieve().bodyToMono(JSONObject.class);}// PUT请求publicMono<JSONObject>put(String q1,JSONObjectJSONObject){return webClient.put().uri(uriBuilder -> uriBuilder .path("/put").queryParam("q1", q1).build()).bodyValue(JSONObject).retrieve().bodyToMono(JSONObject.class);}// DELETE请求publicMono<JSONObject>delete(String q1){return webClient.delete().uri(uriBuilder -> uriBuilder .path("/delete").queryParam("q1", q1).build()).retrieve().bodyToMono(JSONObject.class);}}

效果展示

重学SpringBoot3-WebClient配置与使用详解

重学SpringBoot3-WebClient配置与使用详解

重学SpringBoot3-WebClient配置与使用详解

重学SpringBoot3-WebClient配置与使用详解

4.2 处理复杂响应

@ServicepublicclassApiService{// 获取列表数据publicFlux<JSONObject>getAllUsers(){return webClient.get().uri("/users").retrieve().bodyToFlux(JSONObject.class);}// 处理错误响应publicMono<JSONObject>getUserWithErrorHandling(Long id){return webClient.get().uri("/users/{id}", id).retrieve().onStatus(HttpStatusCode::is4xxClientError, clientResponse ->Mono.error(newRuntimeException("客户端错误"))).onStatus(HttpStatusCode::is5xxServerError, clientResponse ->Mono.error(newRuntimeException("服务器错误"))).bodyToMono(JSONObject.class);}// 使用exchange()方法获取完整响应publicMono<ResponseEntity<JSONObject>>getUserWithFullResponse(Long id){return webClient.get().uri("/users/{id}", id).accept(MediaType.APPLICATION_JSON).exchange().flatMap(response -> response.toEntity(JSONObject.class));}}

4.3 高级用法

@ServicepublicclassApiService{// 带请求头的请求publicMono<JSONObject>getUserWithHeaders(Long id,String token){return webClient.get().uri("/users/{id}", id).header("Authorization","Bearer "+ token).retrieve().bodyToMono(JSONObject.class);}// 带查询参数的请求publicFlux<JSONObject>searchUsers(String name,int age){return webClient.get().uri(uriBuilder -> uriBuilder .path("/users/search").queryParam("name", name).queryParam("age", age).build()).retrieve().bodyToFlux(JSONObject.class);}// 文件上传publicMono<String>uploadFile(FilePart filePart){return webClient.post().uri("/upload").contentType(MediaType.MULTIPART_FORM_DATA).body(BodyInserters.fromMultipartData("file", filePart)).retrieve().bodyToMono(String.class);}}

5. 最佳实践

  1. 合理使用响应式类型

    • 使用 Mono 用于单个对象
    • 使用 Flux 用于集合数据
    • 注意背压处理
  2. 错误处理

    publicMono<JSONObject>getUserWithRetry(Long id){return webClient.get().uri("/users/{id}", id).retrieve().bodyToMono(JSONObject.class).retryWhen(Retry.backoff(3,Duration.ofSeconds(1))).timeout(Duration.ofSeconds(5)).onErrorResume(TimeoutException.class, e ->Mono.error(newRuntimeException("请求超时")));}

  3. 资源管理

    • 使用连接池
    • 设置适当的超时时间
    • 实现优雅关闭

6. 注意事项

  1. WebClient 是非阻塞的,需要注意响应式编程的特性
  2. 合理配置连接池和超时参数
  3. 在生产环境中实现适当的错误处理和重试机制
  4. 注意内存使用,特别是处理大量数据时

7. 与RestTemplate对比

特性WebClientRestTemplate
编程模型响应式、非阻塞同步、阻塞
性能更好一般
资源利用更高效一般
学习曲线较陡平缓
适用场景高并发、响应式系统简单应用、传统系统

8. 总结

WebClient 作为 Spring 推荐的新一代 HTTP 客户端,提供了强大的响应式编程能力和更好的性能。虽然相比 RestTemplate 有一定的学习曲线,但在现代微服务架构中,其带来的好处远超过学习成本。建议在新项目中优先考虑使用WebClient,特别是在需要处理高并发请求的场景下。

参考资料

  • Spring WebClient官方文档
  • Spring Boot官方文档
  • Project Reactor文档
评论(0)条

提示:请勿发布广告垃圾评论,否则封号处理!!

    猜你喜欢
    【MySQL】用户管理

    【MySQL】用户管理

     服务器/数据库  2个月前  2.15k

    我们推荐使用普通用户对数据的访问。而root作为管理员可以对普通用户对应的权限进行设置和管理。如给张三和李四这样的普通用户权限设定后。就只能操作给你权限的库了。

    Cursor Rules 让开发效率变成10倍速

    Cursor Rules 让开发效率变成10倍速

     服务器/数据库  2个月前  1.21k

    在AI与编程的交汇点上,awesome-cursorrules项目犹如一座灯塔,指引着开发者们驶向更高效、更智能的编程未来。无论你是经验丰富的老手,还是刚入行的新人,这个项目都能为你的编程之旅增添一抹亮色。这些规则文件就像是你私人定制的AI助手,能够根据你的项目需求和个人偏好,精确地调教AI的行为。突然间,你会发现AI不仅能理解Next.js的最佳实践,还能自动应用TypeScript的类型检查,甚至主动提供Tailwind CSS的类名建议。探索新的应用场景,推动AI辅助编程的边界。

    探索Django 5: 从零开始,打造你的第一个Web应用

    探索Django 5: 从零开始,打造你的第一个Web应用

     服务器/数据库  2个月前  1.12k

    Django 是一个开放源代码的 Web 应用程序框架,由 Python 写成。它遵循 MVT(Model-View-Template)的设计模式,旨在帮助开发者高效地构建复杂且功能丰富的 Web 应用程序。随着每个版本的升级,Django 不断演变,提供更多功能和改进,让开发变得更加便捷。《Django 5 Web应用开发实战》集Django架站基础、项目实践、开发经验于一体,是一本从零基础到精通Django Web企业级开发技术的实战指南《Django 5 Web应用开发实战》内容以。

    MySQL 的mysql_secure_installation安全脚本执行过程介绍

    MySQL 的mysql_secure_installation安全脚本执行过程介绍

     服务器/数据库  2个月前  1.07k

    mysql_secure_installation 是 MySQL 提供的一个安全脚本,用于提高数据库服务器的安全性

    【MySQL基础篇】概述及SQL指令:DDL及DML

    【MySQL基础篇】概述及SQL指令:DDL及DML

     服务器/数据库  2个月前  482

    数据库是长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。数据库不仅仅是数据的简单堆积,而是遵循一定的规则和模式进行组织和管理的。数据库中的数据可以包括文本、数字、图像、音频等各种类型的信息。

    Redis中的哨兵(Sentinel)

    Redis中的哨兵(Sentinel)

     服务器/数据库  2个月前  308

    ​ 上篇文章我们讲述了Redis中的主从复制(Redis分布式系统中的主从复制-CSDN博客),本篇文章针对主从复制中的问题引出Redis中的哨兵,希望本篇文章会对你有所帮助。