RestTemplate配置和使用
在项目中,如果要调用第三方的http服务,就需要发起http请求,常用的请求方式:第一种,使用java原生发起http请求,这种方式不需要引入第三方库,但是连接不可复用,如果要实现连接复用,需要自己实现管理,相对来说比较麻烦;第二种就是使用第三方的库,比较常用的就是apache的httpclient和okhttp两个包,他们都对http请求进行了封装并且可以管理连接,对于重复使用的连接会有比较好的性能;第三种就是在springboot中使用RestTemplate进行请求,它是对http请求的封装,默认使用的java原生进行请求,也支持整合httpclient和okhttp库,提供很好的封装和扩展性。下面就介绍一下如何在项目中使用和相关配置:
要在项目中使用RestTemplate,首先需要定义一个Bean将它注入到系统中:
@Bean
public RestTemplate restTemplate() {return new RestTemplate();
}
这种方式注入的对象默认使用SimpleClientHttpRequestFactory工厂,它使用java原生方式发起http请求,性能并不好,还有一种注入方式是:
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {return builder.build();
}
RestTemplateBuilder这种注入方式会根据系统中是否引入第三方的http库来灵活选择httpclient工厂,通过跟踪源码发现,目前支持httpclient和okhttp3两个库,如下图:


虽然通过上面的方式注入的RestTemplate会自动选择创建httpclient的工厂,但是该工厂相关参数都是默认配置,有时候并不能满足我们系统的需求,比如要设置读写超时时间,默认的配置中是永远不超时,这样如果请求的第三方系统响应慢会导致整个系统崩溃。
不加任何配置的RestTemplate内容如下:

要调整超时时间,就需要使用下面这种方式注入工厂,并配置相关参数:
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();factory.setConnectTimeout(3000);factory.setReadTimeout(3000);return factory;
}@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {return new RestTemplate(factory);
}
再次查看RestTemplate的内容:

通常情况下我们都不会使用java原生的方式发起http请求,因为每次发起http请求都要重新建立连接,这样会大大降低系统性能,在这个示例中我选择使用apache下的httpclient库扩展,首先需要在项目中引入相关依赖:
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.12</version>
</dependency>
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId><version>4.5.12</version>
</dependency>
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4.13</version>
</dependency>
注意包的版本要匹配,否则会有报错,接下来就是将httpclient注入到RestTemplate中,这里有两种方式,第一种是使用下面的配置
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {return builder.build();
}
它可以检测到系统中引入了httpclient依赖,会自动将原生的工厂类替换为apacheHttpClient的工厂:

但是这种方式使用的配置都是默认的,如连接池大小为20个,超时时间永不超时等。这种配置不能满足我们的需求,这时候就需要根据自己系统的要求调整配置参数了,下面的示例代码是我的一个简单配置:
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.UnsupportedSchemeException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;import javax.net.ssl.SSLException;
import java.io.InterruptedIOException;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;@Configuration
public class RestTemplateConfig {@Beanpublic ClientHttpRequestFactory apacheHttpRequestFactory() {// 重试配置HttpRequestRetryHandler retryHandler = (e, count, context) -> {System.out.println("连接失败次数|" + count);e.printStackTrace();if (count >= 5) { // 假设已经重试了5次,就放弃return false;}// 返回true需要重试if (e instanceof NoHttpResponseException // 请求无响应就重试|| e instanceof ConnectTimeoutException // 连接超时|| e instanceof SocketException // 连接异常|| e instanceof SocketTimeoutException // socket超时) {try {// 重试时间间隔:1sTimeUnit.MILLISECONDS.sleep(1000);} catch (InterruptedException ex) {e.printStackTrace();}return true;}// 返回false不需要重试if (e instanceof SSLException // SSL握手异常不要重试|| e instanceof InterruptedIOException // 中断|| e instanceof UnknownHostException // 目标server不可达|| e instanceof UnsupportedSchemeException // 协议不支持) {return false;}HttpClientContext clientContext = HttpClientContext.adapt(context);HttpRequest request = clientContext.getRequest();// 假设请求是幂等的,就再次尝试return !(request instanceof HttpEntityEnclosingRequest);};Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", SSLConnectionSocketFactory.getSocketFactory()).build();// 连接池配置PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);// 最大连接数connManager.setMaxTotal(1000);// 每个路由最大连接数connManager.setDefaultMaxPerRoute(200);// 超时配置:都为5sRequestConfig reqConfig = RequestConfig.custom().setConnectionRequestTimeout(5000) // 从连接池中获取连接超时时间.setConnectTimeout(5000) // 连接建立超时时间,也就是三次握手完成时间.setSocketTimeout(5000) // 等待服务器响应超时时间.build();// 构建httpclientCloseableHttpClient client = HttpClients.custom().setConnectionManager(connManager).setDefaultRequestConfig(reqConfig).setRetryHandler(retryHandler).build();return new HttpComponentsClientHttpRequestFactory(client);}@Beanpublic RestTemplate restTemplate() {return new RestTemplate(apacheHttpRequestFactory());}
}
通过上面的配置就将自定义的连接参数注入到RestTemplate中了。在使用的位置,只需要引入restTemplate就可以正常使用了:
@Autowired
private RestTemplate restTemplate;
使用restTemplate发起http请求的方法封装为两种形式:一种是ForObject(),如getForObject()、postForObject(),这种只会返回数据;另一种是ForEntity(),如getForEntity()、postForEntity(),这种方式会返回数据和状态信息。
get请求比较简单,下面主要演示一下post请求中的提交表单数据和json数据的示例:
- 提交表单数据:
// 请求地址
String url = "http://localhost:8081/test/add";
// form表单数据
MultiValueMap<String, Object> data = new LinkedMultiValueMap<>();
data.add("name", "james");
data.add("age", 38);
// 请求头部
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
// 发起请求
ResponseEntity<String> result = restTemplate.postForEntity(url, new HttpEntity<>(data, headers), String.class);
- 提交json数据:
// 请求地址
String url = "http://localhost:8081/test/add";
// json数据
String data = "{\"name\":\"james\",\"age\":38}";
// 请求头部
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 发起请求
ResponseEntity<String> result = restTemplate.postForEntity(url, new HttpEntity<>(data, headers), String.class);
相关文章:
RestTemplate配置和使用
在项目中,如果要调用第三方的http服务,就需要发起http请求,常用的请求方式:第一种,使用java原生发起http请求,这种方式不需要引入第三方库,但是连接不可复用,如果要实现连接复用&…...
【Hadoop】YARN容量调度器详解
🦄 个人主页——🎐开着拖拉机回家_Linux,Java基础学习,大数据运维-CSDN博客 🎐✨🍁 🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁&am…...
20个Python实用小技巧!来自十年老程序员的推荐~
文章目录 1.用itertools排列2.单行条件表达式3. 反转字符串4. 使用 Assert 处理异常5. 对多个输入使用拆分6. 用 zip() 转置矩阵7. 资源上下文管理器8. 下划线作为分隔符9. 尝试 f 字符串格式10.用这个技巧交换整数11. 使用 lambda 代替函数12.多次打印无循环13. 将字符串解包为…...
jenkins原理篇——成员权限管理
大家好,我是蓝胖子,前面几节我讲述了jenkins的语法以及我是如何使用jenkins对测试和正式环境进行发布的。但正式环境使用jenkins还有一点很重要,那就是权限管理。正式环境的权限往往不能对所有人开放,以及要做到每次发布都是谁在操…...
13.求面积[有问题]
#include<stdio.h> #include<math.h> #include<bits/stdc.h> using namespace std;void fun(double a,b,c) {double p,c;p (abc)/2;c sqrt(p*(p-a)*(p-b)*(p-c));printf("面积是:%lf",c); }int main(){double a,b,c;scanf("%lf,%…...
【力扣】面试经典150题——哈希表
文章目录 383. 赎金信205. 同构字符串290. 单词规律 383. 赎金信 给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。 magazine 中的每个字符…...
Python批量导入及导出项目中所安装的类库包到.txt文件(补充)
Python批量导入及导出项目中所安装的类库包到.txt文件 生成requirements文件 建议使用,该方式形成文档最简洁: pip list --formatfreeze > requirements.txt...
2023 全栈工程师 Node.Js 服务器端 web 框架 Express.js 详细教程(更新中)
Express 框架概述 Express 是一个基于 Node.js 平台的快速、开放、极简的Web开发框架。它本身仅仅提供了 web 开发的基础功能,但是通过中间件的方式集成了外部插件来处理HTTP请求,例如 body-parser 用于解析 HTTP 请求体,compression 用于压…...
【Leetcode】【数据结构】【C语言】判断两个链表是否相交并返回交点地址
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode *tailAheadA;struct ListNode *tailBheadB;int count10;int count20;//分别找尾节点,并顺便统计节点数量:while(tailA){tailAtailA->next;c…...
Selenium爬取内容并存储至MySQL数据库
前面我通过一篇文章讲述了如何爬取博客摘要等信息。通常,在使用Selenium爬虫爬取数据后,需要存储在TXT文本中,但是这是很难进行数据处理和数据分析的。这篇文章主要讲述通过Selenium爬取我的个人博客信息,然后存储在数据库MySQL中,以便对数据进行分析,比如分析哪个时间段…...
蓝桥等考C++组别六级 007
第一部分:选择题 1、C L6 (15分) 计算一个正整数除以3的余数,以下选项正确的是( )。 A. int m; cin >> m; switch (m % 3) { default: cout << "remainder is 1"; break;// 余…...
集合框架:Set集合的特点、HashSet集合的底层原理、哈希表、实现去重复
Set集合的特点 Set(集合)是一种无序的、不重复的数据结构,它的特点如下: 1. 集合中的元素是无序的:Set 中的元素没有顺序,无法通过索引来访问。 2. 集合中的元素是唯一的:Set 中不允许有重复…...
【T690 之十二】基于方寸EVB2开发板(T690芯片)构建基于GMSSL的文件系统的方式
备注: 1,假设您已对方寸微电子的T690系列芯片的使用方式都有了一定的了解,然后需要构建基于GMSSL的文件系统,此文才对您有意义; 2,若您对方寸微电子的T690芯片不了解,但想进一步了解它ÿ…...
使用Selenium发邮件附件
发邮件可以使用SMTP协议实现程序去发送,但附件的不能太大,一般不超过20M。 以下使用Selenium模拟发送邮件,跳过这个限制,网上找了很多资料,都没有完整实现的,那么自己实现一个,以下代码用Python…...
公共数据这座金矿,授权运营为何是赋能的关键路径?
数据要素市场化正开启下一个关键阶段。 自2014年大数据写入政府工作报告,到全国各地大数据交易所涌现,再到《数据二十条》颁布,中国数据要素产业探索之路已走过近十载。如今,国家大数据局正式成立,更是标志着数据要素…...
昇腾CANN 7.0 黑科技:大模型推理部署技术解密
CANN作为最接近昇腾AI系列硬件产品的一层,通过软硬件联合设计,打造出适合昇腾AI处理器的软件架构,充分使能和释放昇腾硬件的澎湃算力。针对大模型推理场景,CANN最新发布的CANN 7.0版本有机整合各内部组件,支持大模型的…...
OAuth 2.0
OAuth 2.0 是一种授权机制,允许应用程序访问第三方服务的用户数据,而不需要用户提供用户名和密码。其原理包括以下几个步骤: 应用程序向第三方服务请求授权,并提供自己的身份信息。 第三方服务向用户展示授权请求的具体内容和应用…...
7个设计师必备的Figma汉化插件,高效设计超简单!
Figma是一个著名的在线设计工具,拥有来自全球各地的超多设计师都在用,粉丝多多。其强大和灵活的设计功能使许多设计师都喜欢使用它。然而,为了进一步提高设计效率和扩展功能,许多开发人员开发了各种有用的Figma设计的汉化插件。在…...
缓存-基础理论和Guava Cache介绍
缓存-基础理论和Guava Cache介绍 缓存基础理论 缓存的容量和扩容 缓存初始容量、最大容量,扩容阈值以及相应的扩容实现。 缓存分类 本地缓存:运行于本进程中的缓存, 如Java的 concurrentHashMap, Ehcache,Guava Cache。 分布式缓…...
机器人伺服驱动控制环
伺服驱动器的控制环,包括:位置环、速度环、电流环这三种类型。 对于伺服的控制回路,内侧控制环的响应带宽一般会是外侧控制环的5到10倍。也就是说,电流环带宽大致是速度环的5到10倍,速度环带宽则约为位置环的5到10倍…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...
