【SpringBoot整合系列】HttpClient远程访问的示例

前言

  1. 使用Apache的HttpClient库,添加Apache HttpClient的依赖。
  2. 工具类的封装。通常,工具类需要处理GET、POST请求,可能还有其他方法如PUT、DELETE。需要设计一个工具类,提供静态方法,可以发送请求,并处理响应。同时要考虑连接超时、读取超时的设置,以及请求头的配置,比如Content-Type、User-Agent等
  3. 然后,需要处理请求参数的封装。对于GET请求,参数通常是查询字符串;对于POST,可能需要表单参数或者JSON body。因此,工具类可能需要支持不同的参数类型,比如使用Map<String, String>来传递表单参数,或者直接传入一个JSON字符串作为请求体。
  4. 异常处理也是关键。网络请求可能会抛出IOException等异常,工具类需要捕获这些异常,并可能转换成自定义异常,或者返回null,或者记录日志,具体取决于设计选择。需要灵活处理错误,所以可能需要将异常抛出让调用者处理,或者在工具类内部处理并返回错误信息。
  5. 另外,响应处理方面,需要将HttpEntity转换为字符串,并正确关闭连接,确保资源释放。使用EntityUtils.toString时要注意字符编码,通常使用UTF-8。同时,需要关闭HttpResponse和HttpClient,或者使用try-with-resources来自动管理资源,但Apache HttpClient 4.x版本的response关闭可能需要注意,需要确保正确关闭流。

注意事项

  1. 工具类可能包含sendGet和sendPost方法。例如,sendGet接收URL和参数Map,构造带查询参数的URL;sendPost接收URL和可能的表单参数或JSON body,并设置合适的Content-Type。此外,可能需要设置请求头,比如设置JSON的Content-Type为application/json。

  2. 工具类的设计要尽量简洁,可配置。比如,可以允许自定义连接超时时间、读取超时时间,或者设置默认的请求头。可能使用HttpClient的配置,比如RequestConfig来设置超时参数。

  3. 可能的陷阱包括:未正确处理参数编码,比如在GET请求中,参数需要进行URL编码;在POST发送表单时,需要将参数转换为UrlEncodedFormEntity;发送JSON时,要使用StringEntity,并设置Content-Type为application/json。

  4. 需要注意线程安全,HttpClient通常建议重用实例,所以工具类中可能使用静态的CloseableHttpClient实例,并通过静态代码块初始化,确保线程安全。但需确认是否每次请求需要新的实例,或者可以共享。根据Apache HttpClient文档,建议重复使用同一个实例,因为它是线程安全的,并且管理连接池更高效。所以工具类中可以创建一个单例的HttpClient实例。

  5. 另外,工具类可能需要处理不同的Content-Type,比如POST发送JSON时,需要设置对应的头信息,并处理不同的数据体。因此,sendPost可能需要参数来指定发送的数据类型,或者通过方法重载来处理不同情况。

    • 例如,提供sendPostForm用于发送表单,sendPostJson用于发送JSON。或者,在方法中传递一个contentType参数,并根据类型构造不同的HttpEntity。

    • 或者,更灵活的方式是让调用者传入一个HttpEntity对象,这样工具类更通用,但使用起来可能不够方便。所以需要在易用性和灵活性之间权衡。

    • 这里工具类可以提供两个方法:一个处理表单参数(Map类型),另一个处理JSON字符串。

整体思路

  1. 引入Apache HttpClient依赖。

  2. 创建HttpClientUtil类,封装创建HttpClient实例的方法,配置超时等参数。

  3. 实现sendGet方法,处理参数拼接和编码。

  4. 实现sendPost方法,处理表单或JSON数据的提交。

  5. 处理响应,将结果转换为字符串。

  6. 异常处理,关闭资源。

  7. 提供使用示例。

代码示例

Maven依赖

<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.13</version>
</dependency>

HttpClientUtil

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;public class HttpClientUtil {// 超时配置(单位:毫秒)private static final int CONNECT_TIMEOUT = 5000;private static final int SOCKET_TIMEOUT = 5000;// 创建可复用的HttpClient实例private static final CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build()).build();/*** 发送GET请求* @param url 请求地址* @param params 请求参数* @return 响应内容*/public static String sendGet(String url, Map<String, String> params) {HttpGet httpGet = new HttpGet(buildUri(url, params));try (CloseableHttpResponse response = httpClient.execute(httpGet)) {return handleResponse(response);} catch (IOException e) {throw new RuntimeException("GET请求失败", e);}}/*** 发送POST表单请求(application/x-www-form-urlencoded)* @param url 请求地址* @param formData 表单数据* @return 响应内容*/public static String sendPostForm(String url, Map<String, String> formData) {HttpPost httpPost = new HttpPost(url);List<NameValuePair> params = new ArrayList<>();formData.forEach((k, v) -> params.add(new BasicNameValuePair(k, v)));httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));return executePost(httpPost);}/*** 发送POST JSON请求(application/json)* @param url 请求地址* @param json JSON字符串* @return 响应内容*/public static String sendPostJson(String url, String json) {HttpPost httpPost = new HttpPost(url);StringEntity entity = new StringEntity(json, "UTF-8");entity.setContentType("application/json");httpPost.setEntity(entity);return executePost(httpPost);}private static String executePost(HttpPost httpPost) {try (CloseableHttpResponse response = httpClient.execute(httpPost)) {return handleResponse(response);} catch (IOException e) {throw new RuntimeException("POST请求失败", e);}}private static URI buildUri(String url, Map<String, String> params) {try {URIBuilder uriBuilder = new URIBuilder(url);if (params != null) {params.forEach(uriBuilder::addParameter);}return uriBuilder.build();} catch (URISyntaxException e) {throw new IllegalArgumentException("URL格式错误", e);}}private static String handleResponse(CloseableHttpResponse response) throws IOException {int statusCode = response.getStatusLine().getStatusCode();if (statusCode != 200) {throw new RuntimeException("HTTP响应异常,状态码:" + statusCode);}HttpEntity entity = response.getEntity();return entity != null ? EntityUtils.toString(entity, "UTF-8") : null;}
}

使用示例

import java.util.HashMap;
import java.util.Map;public class Example {public static void main(String[] args) {// GET请求示例String getUrl = "https://api.example.com/data";Map<String, String> params = new HashMap<>();params.put("key1", "value1");params.put("key2", "value2");String getResponse = HttpClientUtil.sendGet(getUrl, params);System.out.println("GET响应内容:" + getResponse);// POST表单示例String postFormUrl = "https://api.example.com/submit";Map<String, String> formData = new HashMap<>();formData.put("username", "testuser");formData.put("password", "testpass");String postFormResponse = HttpClientUtil.sendPostForm(postFormUrl, formData);System.out.println("POST表单响应:" + postFormResponse);// POST JSON示例String postJsonUrl = "https://api.example.com/submit-json";String jsonPayload = "{\"name\":\"John\", \"age\":30}";String postJsonResponse = HttpClientUtil.sendPostJson(postJsonUrl, jsonPayload);System.out.println("POST JSON响应:" + postJsonResponse);}
}

总结

工具类特点:

  • 线程安全: 使用单个共享的HttpClient实例,复用连接池资源
  • 超时配置: 统一设置5秒连接/读取超时
  • 编码处理: 统一使用UTF-8编码
  • 异常处理: 将检查异常转换为运行时异常,简化调用
  • 支持多种请求:
    • GET请求(带查询参数)
    • POST表单(application/x-www-form-urlencoded)
    • POST JSON(application/json)
  • 响应处理: 自动验证状态码并转换响应内容

注意事项:

  • 根据实际情况调整超时时间配置
  • 生产环境建议添加日志记录
  • 需要处理其他状态码(如3xx重定向)时可扩展handleResponse方法
  • 如需添加自定义请求头,可扩展方法参数
  • 注意及时释放资源,使用try-with-resources自动关闭响应

可根据实际需求进一步扩展支持:

  • 文件上传
  • HTTPS配置
  • 代理设置
  • 请求重试机制
  • 更完善的异常处理等

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

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

相关文章

Git操作整体流程

文章目录 1.Git创建个人仓库2、Git全局配置3、Git本地管理4. Git本地管理常用命令汇总5、使用Git命令将项目提交到远程码云管理6.使用IDEA进行管理7、Idea里面的终端8、关于提交总结 1.Git创建个人仓库 打开https://gitee.com/&#xff0c;登录个人账号&#xff0c;右上角加号…

MySQL MHA 部署全攻略:从零搭建高可用数据库架构

文章目录 1.MHA介绍2.MHA组件介绍3.集群规划4.服务器初始化5.MySQL集群部署5.1 安装MySQL集群5.2 配置一主两从5.3 测试MySQL主从5.4 赋予MHA用户连接权限 6.安装MHA环境6.1 安装MHA Node6.2 安装MHA Manager 7.配置MHA环境8.MySQL MHA高可用集群测试8.1 通过VIP连接MySQL8.2模…

如何查看java的字节码文件?javap?能用IDEA吗?

编译指令&#xff1a; javac YourProject.java 查看字节码文件的指令&#xff1a; javap -c -l YourProject.class 不添加-c指令就不会显示字节码文件&#xff1a; 不添加 -l 就不会显示源代码和字节码文件的对应关系&#xff1a; 添加-l之后多出来这些&#xff1a; IDEA不太…

1、Window Android 13模拟器 将编译的映像文件导入Android Studio

1、环境准备 编译环境&#xff1a;Ubuntu-18.04.5编译版本&#xff1a;android13-release下载地址&#xff1a;清华大学开源软件镜像站AOSP # 下载repo # 同步代码&#xff1a;repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android13-r…

JUC并发—9.并发安全集合三

大纲 1.并发安全的数组列表CopyOnWriteArrayList 2.并发安全的链表队列ConcurrentLinkedQueue 3.并发编程中的阻塞队列概述 4.JUC的各种阻塞队列介绍 5.LinkedBlockingQueue的具体实现原理 6.基于两个队列实现的集群同步机制 1.并发安全的数组列表CopyOnWriteArrayList …

报错:Cannot read properties of null (reading ‘ce‘)解决方法

背景 工作项目中要做右键菜单打开趋势图弹窗的需求&#xff0c;这个弹窗使用了vue-resizable的第三方插件&#xff0c;这个插件的主要作用是把弹窗设置为可拖拽的效果。这个用vue-resizable做的弹窗已经做好了&#xff0c;在别的项目中能够正常的运行。但是我把它拿过来放在新…

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_process_options

ngx_process_options 声明在 src\core\nginx.c static ngx_int_t ngx_process_options(ngx_cycle_t *cycle); 定义在 src\core\nginx.c static ngx_int_t ngx_process_options(ngx_cycle_t *cycle) {u_char *p;size_t len;if (ngx_prefix) {len ngx_strlen(ngx_prefix);p …

数据结构系列二:包装类+泛型

包装类泛型 一、包装类&#xff08;1&#xff09;基本数据类型和对应的包装类&#xff08;2&#xff09;装箱和拆箱 二、泛型&#xff08;1&#xff09;什么是泛型&#xff08;2&#xff09;引出泛型&#xff08;3&#xff09;语法&#xff08;4&#xff09;泛型类的使用1.语法…

量子计算驱动的金融衍生品定价革命:突破传统蒙特卡洛模拟的性能边界

引言&#xff1a;金融计算的算力困局 某国际投行采用128量子位处理器对亚洲期权组合定价时&#xff0c;其量子振幅估计算法在2.7秒内完成传统GPU集群需要68小时的计算任务。在蒙特卡洛路径模拟实验中&#xff0c;量子随机游走算法将10,000维衍生品的价格收敛速度提升4个数量级…

Spring容器初始化扩展点:ApplicationContextInitializer

目录 一、什么是ApplicationContextInitializer&#xff1f; 1、核心作用2、适用场景 二、ApplicationContextInitializer的使用方式 1、实现ApplicationContextInitializer接口2、注册初始化器 三、ApplicationContextInitializer的执行时机四、实际应用案例 1、动态设置环境…

hive—常用的函数整理

1、size(split(...))函数用于计算分割后字符串数组的长度 实例1&#xff09;&#xff1a;由客户编号列表计算客户编号个数 --数据准备 with tmp_test01 as ( select tag074445270 tag_id,202501busi_mon , 012399931003,012399931000 index_val union all select tag07444527…

vue3 采用xlsx库实现本地上传excel文件,前端解析为Json数据

需求&#xff1a;本地上传excel 文件&#xff0c;但需要对excel 文件的内容进行解析&#xff0c;然后展示出来 1. 安装依赖 首先&#xff0c;确保安装了 xlsx 库&#xff1a; bash复制 npm install xlsx 2. 创建 Vue 组件 创建一个 Vue 组件&#xff08;如 ExcelUpload.v…

若依框架实现动态失效时间JWT Token的实践指南

一、功能需求背景 在前后端分离架构中&#xff0c;JWT&#xff08;JSON Web Token&#xff09;作为无状态认证方案被广泛使用。若依&#xff08;RuoYi&#xff09;框架的TokenService默认采用固定失效时间策略&#xff0c;但在实际开发中常需要根据业务场景动态调整Token有效期…

C++ 设计模式-策略模式

支付策略 #include <iostream> #include <memory> #include <unordered_map> #include <vector> #include <ctime>// 基础策略接口 class PaymentStrategy { public:virtual ~PaymentStrategy() default;virtual std::string name() const 0;…

国产编辑器EverEdit - 如何在EverEdit中管理工程?

1 工程管理 1.1 应用场景 用户创建工程后&#xff0c;会涉及到工程的管理 &#xff0c;比如&#xff1a;打开工程、关闭工程等 1.2 使用方法 1.2.1 打开工程 单击主菜单工程 -> 打开工程&#xff0c;会弹出打开对话框&#xff0c;用户在对话框中选择需要打开的工程文件即…

MYSQL-数据库-DDL-DML-DQL-DCL-基础学习

MySql概念&#xff1a; 建立在关系模型基础上&#xff0c;有多张相互连接的二维表组成的数据库 SQL通用语法&#xff1a; 1.SQL语句可以单行或多行书写&#xff0c;以分号结尾 2.SQL语句可以使用空格/缩进来增强语句的可读性 3.MySQL数据库的SQL语句不区分大小写&#xff0c;关…

SpringBoot核心框架之AOP详解

SpringBoot核心框架之AOP详解 一、AOP基础 1.1 AOP概述 AOP&#xff1a;Aspect Oriented Programming&#xff08;面向切面编程&#xff0c;面向方面编程&#xff09;&#xff0c;其实就是面向特定方法编程。 场景&#xff1a;项目部分功能运行较慢&#xff0c;定位执行耗时…

【RK3588嵌入式图形编程】-SDL2-构建模块化UI

构建模块化UI 文章目录 构建模块化UI1、概述2、创建UI管理器3、嵌套组件4、继承5、多态子组件6、总结在本文中,将介绍如何使用C++和SDL创建一个灵活且可扩展的UI系统,重点关注组件层次结构和多态性。 1、概述 在前面的文章中,我们介绍了应用程序循环和事件循环,这为我们的…

第四届图像、信号处理与模式识别国际学术会议(ISPP 2025)

重要信息 会议官网&#xff1a;www.icispp.com 会议时间&#xff1a;2025年3月28-30日 会议地点&#xff1a;南京 简介 由河海大学和江苏大学联合主办的第四届图像、信号处理与模式识别国际学术会议&#xff08;ISPP 2025) 将于2025年3月28日-30日在中国南京举行。会议主…

低代码与开发框架的一些整合[2]

1.分析的项目资源说明 经过近期的的不断分析与运行对比&#xff0c;最终把注意力集中在了以下几个框架&#xff1a; 01.dibootdiboot.diboot: 写的更少, 性能更好 -> 为开发人员打造的低代码开发平台。Mybatis-plus关联查询&#xff0c;关联无SQL&#xff0c;性能高10倍&a…