【springboot】RestTemplate配置HttpClient连接池
在Java开发中,访问第三方HTTP协议的网络接口,通常使用的连接工具为JDK自带的HttpURLConnection、HttpClient(现在应该称之为HttpComponents)和OKHttp。
这些Http连接工具,使用起来都比较复杂,如果项目中使用的是Spring框架,可以使用Spring自带的RestTemplate来进行Http连接请求。
RestTemplate底层默认的连接方式是Java中的HttpURLConnection,可以使用ClientHttpRequestFactory来指定底层使用不同的HTTP连接方式。
RestTemplate中默认的连接方式
RestTemplate中默认使用的是SimpleClientHttpRequestFactory,我们这里手动创建SimpleClientHttpRequestFactory可以指定连接的超时时间,读数据的超时时间。
package com.morris.user.demo;import com.morris.user.entity.Order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;/*** restTemplate+httpUrlConnection*/
@Slf4j
public class RestTemplateDemo1 {public static void main(String[] args) {SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();factory.setConnectTimeout(3000);factory.setReadTimeout(5000);RestTemplate restTemplate = new RestTemplate(factory);Order[] orders = restTemplate.getForObject("http://127.0.0.1:8020/order/findOrderByUserId?userId=", Order[].class, 1);log.info("orders :{}", orders);}}
SimpleClientHttpRequestFactory底层在创建请求的时候使用的就是HttpURLConnection。
org.springframework.http.client.SimpleClientHttpRequestFactory#createRequest
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {HttpURLConnection connection = openConnection(uri.toURL(), this.proxy);prepareConnection(connection, httpMethod.name());if (this.bufferRequestBody) {return new SimpleBufferingClientHttpRequest(connection, this.outputStreaming);}else {return new SimpleStreamingClientHttpRequest(connection, this.chunkSize, this.outputStreaming);}
}
RestTemplate与HttpClient的结合
只需要在构造RestTemplate实例时传入HttpComponentsClientHttpRequestFactory对象即可。
package com.morris.user.demo;import com.morris.user.entity.Order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;/*** RestTemplate+HttpClient*/
@Slf4j
public class RestTemplateDemo2 {public static void main(String[] args) {HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();RestTemplate restTemplate = new RestTemplate(factory);Order[] orders = restTemplate.getForObject("http://127.0.0.1:8020/order/findOrderByUserId?userId=", Order[].class, 1);log.info("orders :{}", orders);}}
HttpComponentsClientHttpRequestFactory底层在创建请求时使用了HttpClient。
org.springframework.http.client.HttpComponentsClientHttpRequestFactory#createRequest
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {HttpClient client = getHttpClient();HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri);postProcessHttpRequest(httpRequest);HttpContext context = createHttpContext(httpMethod, uri);if (context == null) {context = HttpClientContext.create();}// Request configuration not set in the contextif (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) {// Use request configuration given by the user, when availableRequestConfig config = null;if (httpRequest instanceof Configurable) {config = ((Configurable) httpRequest).getConfig();}if (config == null) {config = createRequestConfig(client);}if (config != null) {context.setAttribute(HttpClientContext.REQUEST_CONFIG, config);}}if (this.bufferRequestBody) {return new HttpComponentsClientHttpRequest(client, httpRequest, context);}else {return new HttpComponentsStreamingClientHttpRequest(client, httpRequest, context);}
}
RestTemplate与HttpClient的在生产环境使用的最佳实践
在构建HttpClient时,经常需要配置很多信息,例如RequestTimeout、ConnectTimeout、SocketTimeout、代理、是否允许重定向、连接池等信息。
在HttpClient,对这些参数进行配置需要使用到RequestConfig类的一个内部类Builder。
这里将这些常用的配置抽取出来放到配置文件中:
package com.morris.user.config;import lombok.extern.slf4j.Slf4j;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;@EnableConfigurationProperties(HttpClientConfig.class)
@ConditionalOnClass(RestTemplate.class)
@Configuration
@Slf4j
public class RestTemplateAutoConfiguration {@Resourceprivate HttpClientConfig httpClientConfig;@Bean@ConditionalOnClass(CloseableHttpClient.class)public RestTemplate httpClientRestTemplate(ClientHttpRequestFactory clientHttpRequestFactory){return new RestTemplate(clientHttpRequestFactory);}@Bean@ConditionalOnClass(CloseableHttpClient.class)public ClientHttpRequestFactory clientHttpRequestFactory(HttpClient httpClient) {HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();clientHttpRequestFactory.setHttpClient(httpClient);clientHttpRequestFactory.setConnectTimeout(httpClientConfig.getRequest().getConnectTimeout());clientHttpRequestFactory.setReadTimeout(httpClientConfig.getRequest().getReadTimeout());clientHttpRequestFactory.setConnectionRequestTimeout(httpClientConfig.getRequest().getConnectionRequestTimeout());clientHttpRequestFactory.setBufferRequestBody(httpClientConfig.getRequest().isBufferRequestBody());return clientHttpRequestFactory;}@Bean@Primary@ConditionalOnClass(CloseableHttpClient.class)public HttpClient httpClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();try {// 设置信任SSL访问SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, (arg0, arg1) -> true).build();httpClientBuilder.setSSLContext(sslContext);// 任何主机都不会抛出SSLException异常HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier);Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()// 注册HTTP和HTTPS请求.register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslConnectionSocketFactory).build();// 使用Httpclient连接池的方式配置PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);poolingHttpClientConnectionManager.setMaxTotal(httpClientConfig.getPool().getMaxTotalConnect());poolingHttpClientConnectionManager.setDefaultMaxPerRoute(httpClientConfig.getPool().getMaxConnectPerRoute());poolingHttpClientConnectionManager.setValidateAfterInactivity(httpClientConfig.getPool().getValidateAfterInactivity());httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(httpClientConfig.getPool().getRetryTimes(), true));httpClientBuilder.setKeepAliveStrategy(connectionKeepAliveStrategy());return httpClientBuilder.build();} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {log.error("初始化HTTP连接池出错", e);throw e;}}/*** 配置长连接保持策略* @return ConnectionKeepAliveStrategy*/public ConnectionKeepAliveStrategy connectionKeepAliveStrategy(){return (response, context) -> {// Honor 'keep-alive' headerHeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));while (it.hasNext()) {HeaderElement he = it.nextElement();String param = he.getName();String value = he.getValue();if (value != null && "timeout".equalsIgnoreCase(param)) {try {return Long.parseLong(value) * 1000;} catch(NumberFormatException error) {log.error("解析长连接过期时间异常", error);}}}HttpHost target = (HttpHost) context.getAttribute(HttpClientContext.HTTP_TARGET_HOST);//如果请求目标地址,单独配置了长连接保持时间,使用该配置Optional<Map.Entry<String, Integer>> any = Optional.ofNullable(httpClientConfig.getPool().getKeepAliveTargetHost()).orElseGet(HashMap::new).entrySet().stream().filter(e -> e.getKey().equalsIgnoreCase(target.getHostName())).findAny();//否则使用默认长连接保持时间return any.map(en -> en.getValue() * 1000L).orElse(httpClientConfig.getPool().getKeepAliveTime() * 1000L);};}}
相关文章:
【springboot】RestTemplate配置HttpClient连接池
在Java开发中,访问第三方HTTP协议的网络接口,通常使用的连接工具为JDK自带的HttpURLConnection、HttpClient(现在应该称之为HttpComponents)和OKHttp。 这些Http连接工具,使用起来都比较复杂,如果项目中使…...
MySQL内置函数使用说明
MySQL函数使用说明 MySQL 是一个流行的关系型数据库管理系统,它提供了许多内置函数来处理和操作数据。这些函数可以简化数据库查询和操作的过程,提高代码的可读性和效率。以下是一些常见的 MySQL 内置函数及其使用说明和示例。 数值函数 ABS() 函数原…...
java后端富文本转word,再传递到浏览器下载。
思路参考,以及所有的工具类都使用了》牧羊人大佬的代码《 有帮助的话不用给到我点赞,给大佬点赞即可 这是前端代码,必须使用get。 post后端返回的流浏览器接收不到(具体原因不详)。get无法传递requestBody,…...
【动态规划算法】-回文串问题题型(34-40题)
💖作者:小树苗渴望变成参天大树🎈 🎉作者宣言:认真写好每一篇博客💤 🎊作者gitee:gitee✨ 💞作者专栏:C语言,数据结构初阶,Linux,C 动态规划算法🎄 如 果 你 …...
STM32基础回顾
文章目录 单片机编程的原理GPIO中断EXTI外部中断定时器中断、串口中断 定时器定时器中断配置过程通用定时器输出比较功能:PWM波的生成定时器的输入捕获功能主从触发模式PWMI模式 定时器的编码器接口 DMA简介通信接口USART软件配置流程:1、仅发数据的配置…...
如何解决电脑无声问题:排除故障的几种常见方法
大家好,今天我们来讨论一下处理电脑没有声音的故障。当你突然发现电脑静音无声时,需要逐步排除可能的问题,但总体而言,声音故障是相对容易解决的。接下来,我们将介绍一些排除电脑无声问题的方法。 第一步:…...
Apache RocketMQ 命令注入
漏洞简介 RocketMQ 5.1.0及以下版本,在一定条件下,存在远程命令执行风险。RocketMQ的NameServer、Broker、Controller等多个组件外网泄露,缺乏权限验证,攻击者可以利用该漏洞利用更新配置功能以RocketMQ运行的系统用户身份执行命令…...
二、搜索与图论6:Dijkstra 模板题+算法模板(Dijkstra求最短路 I, Dijkstra求最短路 II,1003 Emergency)
文章目录 算法模板Dijkstra题目代码模板朴素dijkstra算法堆优化版dijkstra 树与图的存储(1) 邻接矩阵:(2) 邻接表:关于e[],ne[],h[]的理解 关于堆的原理与操作 模板题Dijkstra求最短路 I原题链接题目思路题解 Dijkstra求最短路 II原题链接题目思路题解 1…...
ROS2学习(四)进程,线程与节点的关系
节点与节点执行器 节点,英文是node,在ROS2中,节点是一个抽象的实体,它可以代表某种或某类特定功能的抽象集合体,它可以存在于进程中,也可以存在于线程中。所有ROS2的基础功能最基础的载体是节点,所有的通信…...
【物联网】DMA传输原理与实现详解(超详细)
DMA(Direct Memory Access,直接内存访问)是一种计算机数据传输方式,允许外围设备直接访问系统内存,而无需CPU的干预。 文章目录 Part 1: DMA的工作原理配置阶段:数据传输阶段: Part 2: DMA数据…...
Java类集框架(二)
目录 1.Map(常用子类 HashMap,LinkedHashMap,HashTable,TreeMap) 2.Map的输出(Map.Entry,iterator,foreach) 3.数据结构 - 栈(Stack) 4.数据结构 - 队列(Q…...
爬虫008_流程控制语句_if_if else_elif_for---python工作笔记026
然后我们再来看一下这里的,判断,可以看到 再看一个判断,这里的布尔类型 第二行有4个空格,python的格式 注意这里,输入的age是字符串,需要转一下才行 int可以写到int(intput("阿斯顿法师打发地方")) 这样也可以...
【随笔】五周年创作纪念日
今天收到了 CSDN 的创作五周年提示,正好前几天(7.31)我也成功申请了 CSDN 博客专家,趁这个机会分享一下这几年写博客的感受吧 机缘 关注我比较久的读者应该知道我是从学传统工科半路出家搞计算机的,这里的经历还是比…...
7_分类算法—逻辑回归
文章目录 逻辑回归:1 Logistic回归(二分类问题)1.1 sigmoid函数1.2 Logistic回归及似然函数(求解)1.3 θ参数求解1.4 Logistic回归损失函数1.5 LogisticRegression总结 2 Softmax回归(多分类问题࿰…...
【计算机网络】应用层协议 -- DNS协议
文章目录 1. DNS背景2. 域名简介3. 域名解析过程4. 使用dig查看DNS过程 1. DNS背景 DNS(Domain Name System,域名系统)协议,是一个用来将域名转化为IP地址的应用层协议。 TCP/IP当中通过IP地址和端口号的方式,来确定…...
ES6 - 数组新增的一些常用方法
文章目录 1,Array.from()2,Array.of()3,find(),findIndex(),findLast()和findLastIndex()4,Array.fill()5,keys(),values() 和 entries()6,Array.includes()7,…...
【BEV感知】3-BEV开源数据集
3-BEV开源数据集 1 KITTI1.1 KITTI数据怎么采集?1.2 KITTI数据规模有多大?1.3 KITTI标注了哪些目标?1.4 转换矩阵1.5 标签文件 2 nuScenes2.1 nuScenes Vs KITTI2.2 标注文件 1 KITTI KITTI 1.1 KITTI数据怎么采集? 通过车载相机、激光雷达等传感器采集。 只提供了相机正…...
Kafka-Broker工作流程
kafka集群在启动时,会将每个broker节点注册到zookeeper中,每个broker节点都有一个controller,哪个controller先在zookeeper中注册,哪个controller就负责监听brokers节点变化,当有分区的leader挂掉时,contro…...
第八篇-Tesla P40+ChatGLM2+LoRA
部署环境 系统:CentOS-7CPU: 14C28T显卡:Tesla P40 24G驱动: 515CUDA: 11.7cuDNN: 8.9.2.26目的 验证P40部署可行性,只做验证学习lora方式微调创建环境 conda create --name glm-tuning python3.10 conda activate glm-tuning克隆项目 git clone http…...
调用feign返回错误的数据
bug描述: 在一个请求方法中会调用到feign去获取其他的数据。 List<Demo> list aaaFeignApi.getData(personSelectGetParam);在调用的时候,打断点到feign的地方,数据是存在的,并且有15条。但是返回到上面代码的时候数据就…...
丹青识画系统AI编程辅助:基于代码理解的智能影像处理脚本生成
丹青识画系统AI编程辅助:基于代码理解的智能影像处理脚本生成 最近在折腾一些图像处理的小项目,经常需要写一些重复性的脚本,比如批量调整图片尺寸、识别特定物体轮廓、或者给图片加滤镜。每次都得翻文档、查API,虽然代码不复杂&…...
深度解析:OpenClaw集成MiniMax 2.1遭遇HTTP 401?三步定位+架构级解决方案
–## 一、问题现象与背景 在2026年开源AI智能体工具百花齐放的今天,OpenClaw(前身为Clawdbot/Moltbot)凭借"本地优先、多平台兼容、高度可定制"的核心优势,成为开发者构建专属AI助手的首选框架。然而,当许多…...
Mac窗口置顶终极指南:用Topit解锁你的多任务超能力 [特殊字符]
Mac窗口置顶终极指南:用Topit解锁你的多任务超能力 🚀 【免费下载链接】Topit Pin any window to the top of your screen / 在Mac上将你的任何窗口强制置顶 项目地址: https://gitcode.com/gh_mirrors/to/Topit 还在为频繁切换窗口而烦恼&#x…...
3分钟快速破解:百度网盘提取码智能获取工具终极指南
3分钟快速破解:百度网盘提取码智能获取工具终极指南 【免费下载链接】baidupankey 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 还在为百度网盘分享链接的提取码而烦恼吗?每次遇到加密资源都要手动搜索,既耗时又低效。…...
万象熔炉 | Anything XL详细步骤:错误提示‘low VRAM’的5种应对策略
万象熔炉 | Anything XL详细步骤:错误提示‘low VRAM’的5种应对策略 1. 工具简介与显存挑战 万象熔炉 | Anything XL是一款基于Stable Diffusion XL Pipeline开发的本地图像生成工具,它最大的特点是支持直接加载safetensors单文件权重,无需…...
Qwen3-Reranker-0.6B实战案例:跨语言技术文档智能筛选系统
Qwen3-Reranker-0.6B实战案例:跨语言技术文档智能筛选系统 1. 引言:技术文档管理的痛点与解决方案 在全球化技术团队协作中,工程师们经常面临这样的困境:当需要查找某个技术问题的解决方案时,面对的是分散在Confluen…...
FPGA实现SRIO高速图像传输方案,设计模式(C++)详解——状态模式(State)(2)。
FPGA实现SRIO图像视频传输技术方案 基于Serial RapidIO Gen2协议的高性能图像视频传输方案,采用FPGA作为核心处理平台,提供完整的6套工程源码及技术支持。该方案适用于高速数据采集、实时图像处理等场景。 硬件架构设计 采用Xilinx Kintex-7系列FPGA作为…...
使用OpenGL纹理数组实现高精度实时Lut滤镜
之前写过的文章(使用OpenGL实现滤镜转换的一种思路_轮子初级玩家-CSDN博客),我把一整个Lut滤镜图作为单个纹理贴图,把图像原颜色采样后当作坐标,然后从lut纹理中查找出替换颜色实现滤镜功能,这是最简易的一种滤镜实现方式…...
LN2266 超小型 低电压启动 PWM 控制 升压 DC/DC 电压调整器
■ 产品概述 LN2266 是一款微型、高效率、升压 DC/DC 调整器。电路由电流模 PWM 控制环路,误差放大器,斜波产生电路,比较器和一个功率开关等模块组成。该芯片可在较宽负载范围内高效稳定的工作。低于 1V 的启动电压,可以使用 1-4节…...
【AI实战项目】项目三:序列标注技术深度解析与应用实战
分享一个大牛的人工智能教程。零基础!通俗易懂!风趣幽默!希望你也加入到人工智能的队伍中来!请轻击人工智能教程https://www.captainai.net/troubleshooter 项目背景: 序列标注在AI技术中有⾮常⼴泛的应⽤&am…...
