当前位置: 首页 > news >正文

WebClient vs HttpClient:异同对比

在 Java 开发中,进行网络通信是常见的需求。WebClient 和 HttpClient 是两种常用的用于发送 HTTP 请求的工具。它们都具有相似的功能,但在实现细节和用法上存在一些差异。本文将详细介绍 WebClient 和 HttpClient 的异同,帮助您选择适合您项目需求的工具。

1. 引入依赖

首先,我们需要在项目中引入相应的依赖。对于 WebClient,我们可以使用 Spring WebFlux 提供的 spring-webflux 依赖。对于 HttpClient,我们可以使用 Java 11 提供的 java.net.http 包,无需额外引入依赖。

2. 发送 GET 请求

2.1 使用 WebClient

WebClient client = WebClient.create();
Mono<String> result = client.get().uri("https://api.example.com/users").retrieve().bodyToMono(String.class);
String response = result.block();
System.out.println(response);

2.2 使用 HttpClient

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.example.com/users")).build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

3. 发送 POST 请求

3.1 使用 WebClient

WebClient client = WebClient.create();
Mono<String> result = client.post().uri("https://api.example.com/users").bodyValue("{ \"name\": \"John\", \"age\": 30 }").retrieve().bodyToMono(String.class);
String response = result.block();
System.out.println(response);

3.2 使用 HttpClient

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.example.com/users")).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.ofString("{ \"name\": \"John\", \"age\": 30 }")).build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

4. 配置超时时间

4.1 使用 WebClient

WebClient client = WebClient.builder().clientConnector(new ReactorClientHttpConnector(HttpClient.create().responseTimeout(Duration.ofSeconds(10)))).build();

4.2 使用 HttpClient

HttpClient client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10)).build();

5. 异步请求

5.1 使用 WebClient

WebClient client = WebClient.create();
Mono<String> result = client.get().uri("https://api.example.com/users").retrieve().bodyToMono(String.class);
result.subscribe(response -> System.out.println(response));

5.2 使用 HttpClient

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.example.com/users")).build();
client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenApply(HttpResponse::body).thenAccept(System.out::println);

6. 错误处理

6.1 使用 WebClient

WebClient client = WebClient.create();
Mono<String> result = client.get().uri("https://api.example.com/users").retrieve().onStatus(HttpStatus::isError, response -> Mono.error(new RuntimeException("Request failed"))).bodyToMono(String.class);
String response = result.block();
System.out.println(response);

6.2 使用 HttpClient

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://api.example.com/users")).build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 400) {throw new RuntimeException("Request failed");
}
System.out.println(response.body());

7. 性能和扩展性

7.1 WebClient

  • 基于 Reactor 和 Netty,支持非阻塞 I/O,适用于高并发场景。
  • 集成了 Spring WebFlux 框架,可以与其他 Spring 组件无缝协作。
  • 可以通过自定义 ExchangeFilterFunction 对请求和响应进行拦截和处理。

7.2 HttpClient

  • Java 11 内置的标准库,无需额外引入依赖。
  • 提供了更底层的 API,可以更灵活地控制请求和处理响应。
  • 支持 HTTP/2,性能较好。

8. 结论使用 WebClient 的优点:

  1. 非阻塞、异步操作WebClient 基于响应式编程模型,使用 Reactor 提供的 Mono 和 Flux 类型来表示异步结果。它允许你以非阻塞的方式发送和处理 HTTP 请求,从而提高应用程序的性能和吞吐量。

  2. 简洁的 APIWebClient 提供了简洁而直观的 API,通过链式调用可以方便地设置请求参数、发送请求和处理响应。它的 API 设计使得代码易于阅读和维护。

  3. 内置的异常处理WebClient 提供了丰富的异常处理机制,可以通过 onStatus() 方法处理不同的 HTTP 状态码和错误情况。这使得处理错误和异常变得更加方便和灵活。

  4. 集成 Spring 生态系统WebClient 是 Spring Framework 的一部分,与其他 Spring 组件(如 Spring Boot)无缝集成。它可以与 Spring 的其他功能(如响应式 Web 框架)配合使用,提供全面的开发体验。

9. WebClient 工具类及使用示例

当使用 WebClient 来进行 HTTP 请求时,可以创建一个工具类来封装常用的请求操作。下面是一个示例的 WebClient 工具类,其中包含了 GET、POST、PUT 和 DELETE 方法的实现:

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;public class WebClientUtils {private WebClient webClient;public WebClientUtils(String baseUrl) {this.webClient = WebClient.builder().baseUrl(baseUrl).defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).build();}public <T> Mono<T> get(String uri, Class<T> responseType) {return webClient.get().uri(uri).retrieve().bodyToMono(responseType);}public <T> Mono<T> post(String uri, Object request, Class<T> responseType) {return webClient.post().uri(uri).body(BodyInserters.fromValue(request)).retrieve().bodyToMono(responseType);}public <T> Mono<T> put(String uri, Object request, Class<T> responseType) {return webClient.put().uri(uri).body(BodyInserters.fromValue(request)).retrieve().bodyToMono(responseType);}public <T> Mono<T> delete(String uri, Class<T> responseType) {return webClient.delete().uri(uri).retrieve().bodyToMono(responseType);}
}

使用示例:

public class Main {public static void main(String[] args) {WebClientUtils webClientUtils = new WebClientUtils("https://api.example.com");// 发起 GET 请求webClientUtils.get("/users/1", User.class).subscribe(user -> System.out.println("GET response: " + user));// 发起 POST 请求User newUser = new User("John", "Doe");webClientUtils.post("/users", newUser, User.class).subscribe(user -> System.out.println("POST response: " + user));// 发起 PUT 请求User updatedUser = new User("Jane", "Doe");webClientUtils.put("/users/1", updatedUser, User.class).subscribe(user -> System.out.println("PUT response: " + user));// 发起 DELETE 请求webClientUtils.delete("/users/1", Void.class).subscribe(response -> System.out.println("DELETE response: " + response));}
}

请注意,上述代码中的 User 类是一个自定义的 POJO 类,用于表示用户信息。您需要根据实际情况进行相应的定义和调整。

10. 结论

WebClient 和 HttpClient 都是常用的发送 HTTP 请求的工具,具有相似的功能,但在实现细节和用法上存在一些差异。如果您使用 Spring 框架,且对性能要求较高,可以选择 WebClient。如果您使用的是 Java 11 或更高版本,并且对底层控制和灵活性有要求,可以选择 HttpClient

以上是对 WebClient 和 HttpClient 的异同的详细讲解。希望对大家有所帮助!

👉 💐🌸 公众号请关注 "果酱桑", 一起学习,一起进步! 🌸💐

相关文章:

WebClient vs HttpClient:异同对比

在 Java 开发中&#xff0c;进行网络通信是常见的需求。WebClient 和 HttpClient 是两种常用的用于发送 HTTP 请求的工具。它们都具有相似的功能&#xff0c;但在实现细节和用法上存在一些差异。本文将详细介绍 WebClient 和 HttpClient 的异同&#xff0c;帮助您选择适合您项目…...

ES6中导入import导出export

ES6使用 export 和 import 来导出、导入模块 用法 /** 导出 export *///分别导出 export let name 孙悟空; export function sum(a, b) {return a b; } } //先定义再导出 let age 18 export {age}/** 默认导出 export default */const a 默认导出; export default a;/**…...

【MySQlL学习笔记】(九)内外连接

内外连接 内连接外连接左外连接右外连接 表的连接分为内连和外连 内连接 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选&#xff0c;我们前面学习的查询都是内连接&#xff0c;也是在开发过程中使用的最多的连接查询。 语法&#xff1a; select 字段 from 表…...

敦煌https证书能做些什么

随着互联网技术的不断发展&#xff0c;人们的生活方式和社交方式也发生了巨大的变化。互联网已经成为人们生活中不可或缺的一部分&#xff0c;它不仅提供了方便快捷的信息获取方式&#xff0c;还为人们提供了一个全新的社交平台。 然而&#xff0c;随着互联网的不断发展&#x…...

React笔记(六)React路由

一、React路由简介 React 官方并没有提供对应的路由插件&#xff0c;因此&#xff0c;我们需要下载第三方的路由插件 —— React Router DOM。 React Router 在 2021 年 11 月份的时候更新 v6 的版本。本次课就主要讲解V6版本 二、路由配置 1、下载路由 在项目根目录中&am…...

【算法系列篇】分治-归并

文章目录 前言什么是归并算法1. 排序数组1.1 题目要求1.2 做题思路1.3 Java代码实现 2. 数组中逆序对2.1 题目要求2.2 做题思路2.3 Java代码实现 3. 计算右侧小于当前元素的个数3.1 题目要求3.2 做题思路3.3 Java代码实现 4. 翻转对4.1 题目要求4.2 做题思路4.3 Java代码实现 总…...

word导出为HTML格式教程,同时也导出图片

在写文档教程时&#xff0c;有时需要借鉴人家的专业文档内容&#xff0c;一般都是word格式文档。word直接复制里面的内容&#xff0c;帐帖到网站编辑器会有很多问题&#xff0c;需要二次清楚下格式才行&#xff0c;而且图片是没办法直接复制到编辑器内的。所以最方便的办法是将…...

事务的优化

例子&#xff1a; 举例&#xff1a;假设我们有一个文件上传的uploadFile方法&#xff0c;在这个方法中我们会先执行上传一个文件到分布式文件系统中的方法addMediaFilesToMinIO( )&#xff0c;上传成功后执行文件资源数据入库的addMediaFilesToDb( ),那么这个时候事务应该加在哪…...

VMware虚拟机安装_新虚拟机创建_CentOS镜像导入_linux指令基本操作

文章目录 1 VMware下载安装1.1 下载网址1.2 安装步骤 2 创建虚拟机与CentOS镜像导入2.1 创建新虚拟机2.2 导入CentOS镜像 3 获取ip与连接Xshell3.1 查看虚拟机ip地址3.2 Xshell使用 1 VMware下载安装 1.1 下载网址 https://www.vmware.com/cn/products/workstation-pro/works…...

Git常用命令用法

参考视频&#xff1a;真的是全能保姆 git、github 保姆级教程入门&#xff0c;工作和协作必备技术&#xff0c;github提交pr - pull request_哔哩哔哩_bilibili 1.Git初始化 首先设置名称和邮箱。然后初始化一下&#xff0c;然后就创建了一个空的Git仓库。 PS D:\golang\oth…...

电子元器件采购的数字化转型:智能采购工具的应用

电子元器件采购的数字化转型是采购领域的一项重要趋势&#xff0c;智能采购工具的应用在此过程中发挥了关键作用。以下是智能采购工具在电子元器件采购数字化转型中的应用方面的一些关键点&#xff1a; 供应链可见性&#xff1a; 智能采购工具可以提供对供应链的实时可见性。通…...

【RuoYi移动端】uni-app中通过vuex的store来实现全局变量的修改和读取

一、在store文件中新建csjVar.js文件 const csjVar {csjMess: [{aaa:"ok"},{bbb:"no"}] } export default csjVar 二、修改store文件中新建index.js文件 import Vue from vue import Vuex from vuex import user from /store/modules/user import gette…...

IPv6改造深化之路

01 IPv6改造问题及整体改造思路 随着“十四五”期间国家政策对IPv6深化改造及规模部署的推动&#xff0c;在IPv6改造过程中出现了越来越多的系统性问题&#xff0c;如图1所示。 图1 关于IPv6改造的各种疑问所有跨设备通信的IT软硬件系统均需要处理IP地址&#xff0c;各领域均需…...

atoi(),isdigit(),isspace(),round()源码

atoi()是一个C标准库函数&#xff0c;用于将字符串转换为对应的整数。 以下是atoi()函数的一种简化版本的示例实现&#xff1a; int atoi(const char* str) {int result 0;int sign 1;int i 0;// 处理空格while (isspace(str[i])) {i;}// 处理正负号if (str[i] - || str[…...

C# 播放音频文件(播放提示音)

使用SoundPlayer播放声音 System.Media名称空间下的类SoundPlayer 可以让我们很方便的播放wav波形声音文件。SoundPlayer类其实就是对winmm.dll文件中API函数的封装。 首先引入命名空间&#xff1a; using System.Media; SoundPlayer player new SoundPlayer(); player.Sou…...

一种编程语言,

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…...

云原生Kubernetes:K8S常用服务端口

目录 一、理论 1.K8S常用服务端口号 一、理论 1.K8S常用服务端口号 &#xff08;1&#xff09;K8S集群 表1 K8S集群端口 协议端口号K8S集群TCP22使用主机驱动通过SSH进行节点配置TCP53集群DNS服务UDP53集群DNS服务TCP2376主机驱动与Docker守护进程通信的TLS端口TCP2379et…...

clickhouse调优配置

一、官方文档地址 clickhouse的配置项主要在 config.xml 或 users.xml 中&#xff0c; 基本上都在 users.xml 里 config.xml https://clickhouse.tech/docs/en/operations/server-configuration-parameters/settings/ users.xml https://clickhouse.tech/docs/en/operatio…...

pdf文件打开后部分文字无法显示

场景&#xff1a;pdf文件在系统内预览正常&#xff0c;但是下载到本地电脑上&#xff0c;使用wps查看&#xff0c;部分标题会消失&#xff0c;只有标题里面的数字还能显示出来 经过一系列排查&#xff0c;发现查看的电脑上缺失了字体&#xff0c;使用wps查看时&#xff0c;缺失…...

MCS-51单片机温度控制系统的设计

一、项目介绍 注塑机是一种常用的制造设备&#xff0c;用于生产塑料制品。在注塑机的工作过程中&#xff0c;溶胶必须达到一定的温度才能被注入模具中进行成型。因此&#xff0c;在注塑机的生产过程中&#xff0c;温度控制是非常重要的一环。 本项目基于MCS-51单片机设计了一…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...