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倍…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
