Spring WebClient 基于响应式编程模型的HTTP客户端

news2025/1/17 1:19:49

图片

一、简介

WebClient是一个非阻塞的、可扩展的、基于Reactive Streams规范的HTTP客户端。它提供了一种简洁的方式来进行HTTP请求,并且可以很好地与其他Spring组件集成。WebClient支持同步和异步操作,使得它非常适合用于构建响应式应用程序。

WebClient允许开发者通过构建链式的HTTP请求和响应处理函数来构建异步和非阻塞式的HTTP客户端。它支持多种HTTP方法、请求和响应处理、错误处理、HTTP认证和与RESTful服务交互。

二、特性

非阻塞:WebClient使用非阻塞I/O模型,这意味着它可以在等待服务器响应时执行其他任务,从而提高应用程序的性能。

可扩展性:WebClient可以轻松地与其他Spring组件集成,如Spring MVC、Spring Data REST等。此外,它还支持自定义拦截器和转换器,以满足特定的需求。

支持反应式编程:WebClient完全符合Reactive Streams规范,因此可以很好地与响应式编程框架(如RxJava、Reactor等)一起使用。

简化HTTP请求:WebClient提供了简洁的API,使得发送HTTP请求变得更加容易。例如,你可以使用webClient.get()方法来发送一个GET请求,或者使用webClient.postForEntity()方法来发送一个POST请求并接收一个实体对象。

三、WebClient与RestTemplate区别

RestTemplate是Spring提供的一个基于模板化的HTTP客户端,它已经过时,不再建议使用。以下是WebClient与RestTemplate的一些主要区别:

  1. 非阻塞:RestTemplate是非阻塞的,而WebClient默认情况下是阻塞的。但是,你可以通过设置client.configurator().setConnectTimeout(Duration.ofSeconds(10))来让WebClient在连接超时时抛出异常。

  2. 可扩展性:WebClient更容易与其他Spring组件集成,因为它是一个更高级别的抽象。而RestTemplate需要手动创建HttpComponentsClientHttpRequestFactory实例,这可能会比较复杂。

  3. 支持反应式编程:WebClient完全符合Reactive Streams规范,因此可以很好地与响应式编程框架一起使用。而RestTemplate不支持反应式编程。

  4. 错误处理:RestTemplate的错误处理是通过回调函数进行的,这使得错误处理变得复杂。而WebClient的错误处理更加直观,因为它支持直接使用try-catch语句捕获异常。

  5. 配置选项:RestTemplate的配置选项较少,而WebClient提供了更多的配置选项,如连接超时、重试策略等。

四、Spring Boot集成WebClient

在Spring Boot中集成WebClient非常简单,只需添加以下依赖即可:

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

接下来,我们创建一个WebClient实例,并演示如何发送同步和异步请求:


import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

public class WebClientExample {
    public static void main(String[] args) {
        // 创建一个WebClient实例
        WebClient webClient = WebClient.create("https://api.example.com");

        // 发送一个GET请求并接收一个Mono<String>对象(同步请求)
        Mono<String> response = webClient.get()
                .uri("/resource")
                .retrieve()
                .bodyToMono(String.class);
        response.subscribe(System.out::println, Throwable::printStackTrace); // 打印响应结果或错误信息

        // 发送一个POST请求并接收一个Mono<String>对象(异步请求)
        Mono<String> asyncResponse = webClient.post()
                .uri("/resource")
                .bodyValue("Hello, World!") // 设置请求体内容
                .retrieve() // 返回响应体而不是完整的响应对象
                .bodyToMono(String.class); // 将响应体转换为Mono<String>对象
        asyncResponse.subscribeOn(Schedulers.boundedElastic()) // 指定异步执行的任务线程池
                .subscribe(System.out::println, Throwable::printStackTrace); // 打印响应结果或错误信息
    }
}

在这个示例中,我们首先创建了一个WebClient实例,然后使用get()方法发送一个GET请求并接收一个Mono<String>对象。我们使用uri()方法指定请求的URI,然后调用retrieve()方法来获取响应体。最后,我们使用bodyToMono()方法将响应体转换为一个Mono<String>对象,并订阅它以打印结果。

五、网络客户端

Spring WebClient是一个基于Reactive Streams规范的非阻塞式HTTP客户端,它提供了创建网络客户端的功能。下面是使用Spring WebClient创建网络客户端的示例代码:

import org.springframework.web.reactive.function.client.WebClient;

public class WebClientExample {
    public static void main(String[] args) {
        // 创建一个WebClient实例
        WebClient webClient = WebClient.create("https://api.example.com");

        // 发送一个GET请求并接收一个Mono<String>对象
        Mono<String> response = webClient.get()
                .uri("/resource")
                .retrieve()
                .bodyToMono(String.class);

        // 订阅响应并打印结果
        response.subscribe(System.out::println);
    }
}

在这个示例中,我们首先创建了一个WebClient实例,然后使用get()方法发送一个GET请求并接收一个Mono<String>对象。我们使用uri()方法指定请求的URI,然后调用retrieve()方法来获取响应体。最后,我们使用bodyToMono()方法将响应体转换为一个Mono<String>对象,并订阅它以打印结果。

除了发送GET请求外,我们还可以使用其他方法来发送不同类型的请求,例如POST、PUT和DELETE等。例如,我们可以使用post()方法发送一个POST请求:


import org.springframework.web.reactive.function.client.WebClient;

public class WebClientExample {
    public static void main(String[] args) {
        // 创建一个WebClient实例
        WebClient webClient = WebClient.create("https://api.example.com");

        // 发送一个POST请求并接收一个Mono<String>对象
        Mono<String> response = webClient.post()
                .uri("/resource")
                .bodyValue("Hello, World!") // 设置请求体内容
                .retrieve() // 返回响应体而不是完整的响应对象
                .bodyToMono(String.class); // 将响应体转换为Mono<String>对象

        // 订阅响应并打印结果
        response.subscribe(System.out::println);
    }
}

在这个示例中,我们使用post()方法发送一个POST请求,并使用bodyValue()方法设置请求体内容。我们同样使用retrieve()方法来获取响应体,并使用bodyToMono()方法将响应体转换为一个Mono<String>对象。最后,我们订阅这个Mono对象以打印响应结果。

六、错误处理机制

Spring WebClient提供了多种错误处理机制,包括异常处理、重试策略和自定义错误处理。下面将分别介绍这些错误处理方式,并给出相应的代码示例。

6.1 异常处理

WebClient支持使用onErrorResume方法来处理请求过程中发生的异常。例如:


import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public class WebClientExample {
    public static void main(String[] args) {
        // 创建一个WebClient实例
        WebClient webClient = WebClient.create("https://api.example.com");

        // 发送一个GET请求并处理异常
        Mono<String> response = webClient.get()
                .uri("/resource")
                .retrieve()
                .onErrorResume(e -> {
                    // 打印异常信息
                    System.err.println("Request failed: " + e.getMessage());
                    // 返回一个空的Mono对象,表示请求失败
                    return Mono.empty();
                });

        response.subscribe(System.out::println, Throwable::printStackTrace); // 打印响应结果或错误信息
    }
}

在这个示例中,我们使用onErrorResume方法来处理请求过程中发生的异常。当发生异常时,我们打印异常信息,并返回一个空的Mono对象,表示请求失败。

6.2 重试策略

WebClient支持多种重试策略,如固定延迟重试、指数退避重试等。以下是使用固定延迟重试的示例:


import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public class WebClientRetryExample {
    public static void main(String[] args) {
        // 创建一个WebClient实例
        WebClient webClient = WebClient.builder()
                .baseUrl("https://api.example.com")
                .clientConnector(new ReactorClientHttpConnector())
                .build();

        // 发送一个GET请求并设置重试策略
        Mono<String> response = webClient.get()
                .uri("/resource")
                .retrieve()
                .bodyToMono(String.class)
                .retryWhen(e -> e instanceof java.net.SocketTimeoutException || e instanceof java.net.UnknownHostException) // 当发生SocketTimeoutException或UnknownHostException时进行重试
                .delayElements(Duration.ofSeconds(1)); // 设置重试间隔为1秒

        response.subscribe(System.out::println, Throwable::printStackTrace); // 打印响应结果或错误信息
    }
}

在这个示例中,我们使用retryWhen方法来设置重试策略。当发生SocketTimeoutException或UnknownHostException时,我们进行重试。同时,我们使用delayElements方法来设置重试间隔。

6.3 自定义错误处理

除了使用异常处理和重试策略外,你还可以通过实现ClientResponse接口来自定义错误处理逻辑。例如:


import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public class CustomErrorHandlingExample {
    public static void main(String[] args) {
        // 创建一个WebClient实例
        WebClient webClient = WebClient.create("https://api.example.com");

        // 发送一个GET请求并自定义错误处理逻辑
        Mono<String> response = webClient.get()
                .uri("/resource")
                .retrieve()
                .onStatus(status -> status.is4xxClientError(), clientResponse -> {
                    // 当发生4xx客户端错误时,返回一个空的Mono对象,表示请求失败
                    return Mono.empty();
                })
                .onStatus(status -> status.is5xxServerError(), clientResponse -> {
                    // 当发生5xx服务器错误时,返回一个空的Mono对象,表示请求失败
                    return Mono.empty();
                });

        response.subscribe(System.out::println, Throwable::printStackTrace); // 打印响应结果或错误信息
    }
}

在这个示例中,我们使用onStatus方法来自定义错误处理逻辑。当发生4xx客户端错误或5xx服务器错误时,我们返回一个空的Mono对象,表示请求失败。

七、结语

在 Spring Framework 5.0 及更高版本中,RestTemplate 已被弃用,取而代之的是较新的 WebClient。由于 RestTemplace 已弃用,开发人员应开始使用 WebClient 进行 REST 调用,非阻塞 I/O 调用会提高应用程序性能。

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1081220.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全网都在用的英语配音软件~

现在有很多智能配音软件都可以输入文字内容生成语音&#xff0c;让我们给视频配音的过程更加简单方便。但目前很多比较常见的文字转语音软件都只能配音中文&#xff0c;而无法配音英语。想要智能生成英语的配音的小伙伴看过来&#xff0c;给大家推荐一款超实用的英语配音软件&a…

从零开始学习 Java:简单易懂的入门指南之多线程(三十四)

多线程 1.实现多线程1.1简单了解多线程1.2并发和并行1.3进程和线程1.4实现多线程方式一&#xff1a;继承Thread类【应用】1.5实现多线程方式二&#xff1a;实现Runnable接口【应用】1.6实现多线程方式三: 实现Callable接口【应用】1.7设置和获取线程名称【应用】1.8线程休眠【应…

Linux系统编程:编译过程以及GDB调试

编译工具链SDK&#xff08;Software Development Kit&#xff09; 在windows下编写程序&#xff0c;我们通常会用IDE&#xff0c;比如idea、vs等&#xff0c;这些工具将编译链接什么的全都暗地里解决好了我们只要写程序就行&#xff0c;但很明显&#xff0c;在Linux系统下做不…

网吧2023:中国电竞的滚烫夏天

【潮汐商业评论/原创】 随着亚运会“中国队拿下电竞首金”登上微博热搜&#xff0c;电竞与网游又一次占据着网民视野中的C位&#xff0c;场内电竞中心的比赛热血澎湃&#xff0c;场外网吧的欢呼声也此起彼伏。 中国玩家的网游之路大多是从网吧里一排17英寸的大屁股显示器前开…

大模型之Prompt研究和技巧

大模型之Prompt研究和技巧 大模型之Prompt编写简介组成技术Zero-ShotFew-shotCOTCOT-SCTOTGoTReAct 大模型之Prompt编写 简介 Prompt是是给 AI **模型的指令&#xff0c;**一个简短的文本输入&#xff0c;用于引导AI模型生成特定的回答或执行特定任务。 Prompt是你与语言模型沟…

milvus测试

milvus测试 目标 其实&#xff0c;我应该弄明白他的输入输出分别是什么&#xff1f; 输入是图片&#xff0c;图片经过ml模型进行特征提取&#xff0c;再在milvus中进行存储或者检索 部署 ✘ delldell-Precision-3630-Tower  /nvme/baum/git-project/milvus   master …

【EI会议征稿】第三届计算建模、仿真与数据分析国际学术会议(CMSDA 2023)

第三届计算建模、仿真与数据分析国际学术会议(CMSDA 2023) 第三届计算建模、仿真与数据分析国际学术会议(CMSDA 2023)将于2023年12月22-24日即将在中国海南省三亚市召开。首届计算建模、仿真与数据分析国际学术会议已于2021、2022年连续成功举办&#xff0c;吸引了近200名计算机…

投你500万,你想做什么?头脑风暴一下 无限想像 有想法的人都能投 数学

投你500万&#xff0c;你想做什么&#xff1f;头脑风暴一下 我要投我自己 1、先出国读个博。8年 30万/年 240万 2、另外260万想研究啥就研究啥。比如 3栖动物&#xff1a;把人改造成3栖动物&#xff0c;可以在水里&#xff0c;海洋里&#xff0c;陆地上&#xff0c;天空都能生…

计算机的层次与编程语言

文章目录 前言一、程序翻译与程序解释二、计算机的层次与编程语言1.硬件逻辑层2.微程序机器层3.传统机器层4.操作系统层5.汇编语言层6.高级语言层7.应用层 总结 前言 今天给大家介绍一下计算机的层次与编程语言&#xff0c;包含两个板块&#xff1a;程序翻译与程序解释、计算机…

Vue + moment 实现自定义日历

moment moment是一个js工具库&#xff0c;这个库中封装的是日期时间的方法&#xff0c;功能很全面。可以去moment官网看看&#xff0c;它的中文文档介绍的也很详细&#xff0c;主要是看一下方法的使用。附上官网地址&#xff1a;添加链接描述 日历案例 日历的逻辑&#xff1a;…

servlet基础知识

目录 什么是servlet概念/定义作用 servlet容器概念/是什么作用如何配置和管理 servlet生命周期有哪些生命周期每个周期中可以执行哪些操作 创建和编写servlet如何创建一个简单的servletservlet类的结构是什么样的如何处理HTTP请求和响应 servlet映射和URL模式什么是servlet映射…

Unity2017适配安卓12

测试版本为Unity2017.4.25f1 1.在自定义AndroidManifest.xml&#xff08;位于Assets\Plugins\Android\&#xff09;中添加android:exported"true" <?xml version"1.0" encoding"utf-8"?> <manifestxmlns:android"http://schema…

现在学网络安全主要是实战还是打CTF?

当然是实战了!!! 现在的CTF题目是基本不贴近实战的&#xff0c;逻辑结构并不合理&#xff0c;而且出题手十有八九是学生&#xff0c;并没有从教育出发的意义&#xff0c;只是比赛、竞技。 如果说你未来要从事网络安全行业的话肯定是以实战为主的&#xff01;企业在招聘时更多…

如何基于先进视频技术,构建互联网视频监控安全管理平台解决方案

一、建设思路 依托互联网&#xff0c;建设一朵云&#xff0c;实现各类二三类视频资源统一接入&#xff0c;实现天网最后100米、10米、1米的全域覆盖。 依托人工智能与互联网技术&#xff0c;拓展视频资源在政府、社会面等多领域的全面应用&#xff1b;建设与运营模式并存&…

《向量数据库指南》——押注向量数据库 挑战颇多

押注向量数据库 挑战颇多 作为今年以来的热门技术赛道,向量数据库已吸引了大量厂商和创业团队入场,先发者与后来者,老牌厂商与新生力量之间的竞争正在持续升温。 但值得注意的是,向量数据库真的值得厂商全力投入吗? 在《为什么你不应该投资向量数据库?》一文中,吴英骏…

3DEXPERIENCE® SOLIDWORKS® 新功能

先前版本的兼容性 优点 即使其他用户正在使用旧版 SOLIDWORKS&#xff0c;也能轻松与其 协作。 • 通过将您的 3DEXPERIENCE SOLIDWORKS 设计作品保存为旧 版本&#xff0c;与使用旧版本的供应商无缝协作。 • 将零件、装配体和工程图保存为最新版本前两年之内的 3DEXPERIENC…

仿真软件Proteus8.9 SP2 Pro 下载、安装、汉化详细图文教程

Proteus8.9 安装教程 视频教程一、安装软件解压二、软件安装常见问题及解决方法&#xff1a;三、汉化 Proteus8.9 SP2 Pro 安装教程 本破解教程仅供个人及 proteus 8.9粉丝们交流学习之用&#xff0c;请勿用于商业用途&#xff0c; 谢谢支持。此版本为Proteus8.9 SP2 Pro。其他…

Httpd(一)

介绍 httpd是apache超文本传输协议(HTTP)服务器的主程序。被设计为一个独立运行的后台进程&#xff0c;它会建立一个处理请求的子进程或线程的池。 特性 高度模块化&#xff1a;core modules DSO&#xff1a;Dynamic Shared Object 动态加载/卸载 MPM&#xff1a;multi-p…

TCP/IP(八)TCP的连接管理(五)四次握手

一 tcp连接断开 每一个TCP报文的超时重传都由一个特定的内核参数来控制 ① 四次握手的过程 遗留&#xff1a; 谁先发送FIN包,一定是client吗? --> upload和download补充&#xff1a; 主动和被动断开连接的场景 "四次握手过程描述" F --> FIN --> F…

LeetCode-144-二叉树的前序遍历

题目描述&#xff1a; 题目链接&#xff1a;LeetCode-144-二叉树的前序遍历 递归法 解题思路&#xff1a; 方法一&#xff1a;递归。 要先清楚前序遍历的顺序&#xff1a;先根节点&#xff0c;再左子树&#xff0c;再右子树。 然后是递归三部曲&#xff1a; 确定递归函数的参数…