WebClient vs HttpClient:异同对比

news2024/11/24 23:05:04

在 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 的异同的详细讲解。希望对大家有所帮助!

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

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

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

相关文章

leetcode 205. 同构字符串

2023.9.6 本题维护两个映射表map&#xff0c;若发现无法对应则返回false。 代码如下&#xff1a; class Solution { public:bool isIsomorphic(string s, string t) {unordered_map<char,char> m1;unordered_map<char,char> m2;for(int i0; i<s.size(); i){//相…

信息化战略规划-CRO-SCM-应用集成-电子商务

信息化战略规划-CRO-SCM-应用集成-电子商务 信息化战略体系(重点)信息系统战略规划&#xff08;重点&#xff09;客户关系管理&#xff08;重点&#xff09;供应链管理企业应用集成电子商务 信息化战略体系(重点) 企业战略&#xff1a;目标 企业战略规划&#xff1a;实现目标的…

【EI/SCOPUS会议征稿】第二届环境遥感与地理信息技术国际学术会议(ERSGIT 2023)

第二届环境遥感与地理信息技术国际学术会议 2023 2nd International Conference on Environmental Remote Sensing and Geographic Information Technology 第二届环境遥感与地理信息技术国际学术会议&#xff08;ERSGIT 2023&#xff09;定于2023年11月10-12日在中国陕西西安…

数据库设计:防止MySQL字段名与关键字相撞,保护数据完整性!

MySQL是一款广泛应用的关系型数据库管理系统&#xff0c;对于数据库设计而言&#xff0c;字段名的选择是至关重要的一环。不小心选择了和MySQL关键字相同的字段名可能导致严重的数据完整性问题。下面将深入探讨如何防止MySQL字段名与关键字相撞&#xff0c;以保护数据的完整性。…

6.(高级示例篇)cesium暗色系地图样式地图(颜色滤镜)

注&#xff1a;高级示例博客不提供源码 地图之家总目录&#xff08;订阅之前建议先查看该博客&#xff09; 效果如下所示&#xff1a; cesium暗色系地图样式地图&#xff08;颜色滤镜&#xff09;

Multimodel Image synthesis and editing:The generative AI Era

1.introduction 基于GAN和扩散模型&#xff0c;通过融入多模态引导来调节生成过程&#xff0c;从不同的多模态信号中合成图像&#xff1b;是为多模态图像合成和编辑使用预训练模型&#xff0c;通过在GAN潜在空间中进行反演&#xff0c;应用引导函数&#xff0c;或调整扩散模型…

鞋业的数字化转型:3D建模与3D打印

3D打印正在成为时尚行业的一笔重要资产。 正如我们在之前的博客文章中看到的那样&#xff0c;制鞋行业实际上正在充分利用这种新的制造工艺。 这是改进许多不同公司的原型设计和生产流程的一种方法。 但为了改进这些流程&#xff0c;获得正确的 3D 建模软件非常重要。 即使你不…

rknn_server启动方法

rknn_server: 是一个运行在板子上的后台代理服务&#xff0c;用于接收PC通过USB传输过来的协议&#xff0c;然后执行板端runtime对应的接口&#xff0c;并返回结果给PC。 当rknn_server没有启动&#xff0c;则在上位机和瑞芯微开发板的连扳调试&#xff0c;容易出现如下错误&a…

安防监控/视频汇聚/视频云存储EasyCVR平台v3.3版本AI智能分析网关V3接入教程2.0

TSINGSEE的边缘计算硬件智能分析网关V3内置多种AI算法模型&#xff0c;包括人脸、人体、车辆、车牌、行为分析、烟火、入侵、聚集、安全帽、反光衣等等&#xff0c;可应用在安全生产、通用园区、智慧食安、智慧城管、智慧煤矿等场景中。将网关硬件结合TSINGSEE青犀的视频汇聚/安…

手写Spring:第10章-对象作用域和FactoryBean

文章目录 一、目标&#xff1a;对象作用域和FactoryBean二、设计&#xff1a;对象作用域和FactoryBean三、实现&#xff1a;对象作用域和FactoryBean3.0 引入依赖3.1 工程结构3.2 Spring单例、原型以及FactoryBean功能类图3.3 Bean的作用范围定义和xml解析3.3.1 Bean对象信息定…

【C语言】——三子棋游戏

目录 Ⅰ.初始页面&#xff1a; Ⅱ.游戏页面 Ⅲ.玩家下棋 Ⅳ.电脑下棋 Ⅴ.判断输赢 结果演示。 代码整体实现 1.test.c 2.game.c 3.game.h ① 前言 三子棋是一款非常经典的小游戏&#xff0c;三点一线即为成功&#xff0c;初学代码者&#xff0c;基本上都会接触这款小游戏…

在项目管理中,项目经理需要了解哪些内容?

在项目管理中&#xff0c;没有绝对的完美&#xff0c;每个项目和项目经理都有可以改进的空间。即使在项目交付时&#xff0c;也会面临各种问题和关系&#xff0c;使得项目经理难以充分应用最佳实践。 项目经理接触项目的第一步是沟通项目的目标&#xff0c;通过与利益相关者的…

论文研读|生成式跨模态隐写发展综述

前言&#xff1a;本文介绍近5年来生成式跨模态隐写领域的相关工作。 相关阅读&#xff1a;生成式文本隐写发展综述 不同于文本隐写&#xff0c;跨模态隐写需要考虑不同模态间的相关性&#xff0c;常见的跨模态场景有&#xff1a;Image-to-Text&#xff08;如图像描述&#xff…

【校招VIP】测试计划之loadrunner分析

考点介绍&#xff1a; LoadRunner&#xff0c;是一种预测系统行为和性能的负载测试工具。通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题&#xff0c;LoadRunner能够对整个企业架构进行测试。企业使用LoadRunner能优化性能和加速应用系统的发布周期。校…

C语言 数据结构与算法 I

C语言-数据结构与算法 C语言基础 因为之前写算法都是用C&#xff0c;也有了些C基础&#xff0c;变量常量数据类型就跳过去吧。 首先是环境&#xff0c;学C时候用Clion&#xff0c;C语言也用它写吧~ 新建项目&#xff0c;选C执行文件&#xff0c;语言标准。。。就先默认C99吧…

你折腾一天都装不上的插件,函数计算部署 Stable Diffusion 都内置了

在进行函数计算 Stable Diffusion 答疑的过程中&#xff0c;遇到很多同学在装一些插件的过程中遇到了难题&#xff0c;有一些需要安装一些依赖&#xff0c;有一些需要写一些代码&#xff0c;很多时候安装一个插件就能折腾几天&#xff0c;我们收集了很多同学需要的插件&#xf…

OpenWrt通过终端查询版本

一、cat /etc/banner 二、cat /proc/version 三、cat /etc/openwrt_release 四、uname -a 五、opkg --version

从事网络安全行业 35岁会被淘汰吗?

根据我国信息部门统计显示&#xff1a;今后5年&#xff0c;我国从事网络建设、网络应用和网络服务的新型网络人才&#xff0c;尤其是网络工程师需求将达到60—100万人&#xff0c;而现有符合新型网络人才要求的人还不足20万人。不饱和度高达80%&#xff0c;人才需求量大。 这说…

1065 A+B and C (64bit)

题&#xff1a;点我 题目大意&#xff1a; 这题虽然看着像签到&#xff0c;然鹅签不过去。 因为我最初写的沙雕代码是&#xff1a; #include<iostream> #include<cstdio> using namespace std; int main(void) {int t;scanf("%d", &t);for (int i …

【C++从0到王者】第二十七站:搜索二叉树

文章目录 前言一、二叉搜索树的概念二、二叉搜索树的实现1.二叉树的结点定义2.二叉搜索树的结构3.二叉搜索树的构造函数4.二叉搜索树的插入&#xff08;非递归&#xff09;5.二叉搜索树的中序遍历&#xff08;排序&#xff09;6.二叉搜索树的查找&#xff08;非递归&#xff09…