RestTemplate详解

一、概述

文章参考Spring之RestTemplate详解

1.1介绍

现如今的 IT 项目,由服务端向外发起网络请求的场景,基本上处处可见!
传统情况下,在服务端代码里访问 http 服务时,一般会使用 JDK 的 HttpURLConnection 或者 Apache 的 HttpClient,不过这种方法使用起来太过繁琐,而且 api 使用起来非常的复杂,还得操心资源回收。

以下载文件为例,通过 Apache 的 HttpClient方式进行下载文件,会很复杂
其实Spring已经为我们提供了一种简单便捷的模板类来进行操作,它就是RestTemplate

1.2‘什么是RestTemplate?

  • RestTemplate是Spring提供的进行远程调用客户端
  • RestTemplate提供了很多远程调用的方法,能够大大提高客户端的编写效率。
    调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求
  • 官网地址RestTemplate (Spring Framework 6.0.11 API)

使用 使用restTemplate访问restful接口非常的简单粗暴无脑。 (url, requestMap, ResponseBean.class)这三个参数分别代表  REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。 

1.3配置

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

同时,将RestTemplate配置初始化为一个Bean

@Configuration
public class RestTemplateConfig
{@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}
}

 @LoadBalanced

@LoadBalanced注解是Spring Cloud中的一个注解,用于在RestTemplate上启用客户端负载均衡。当使用Spring Cloud和Netflix Eureka等服务发现和注册中心时,可以使用@LoadBalanced注解让RestTemplate自动从服务注册表中选择一个可用的服务实例进行调用。

注意,这种初始化方法,是使用了JDK自带的HttpURLConnection作为底层HTTP客户端实现。

ClientHttpRequestFactory接口主要提供了三种实现方式

  • 一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接
  • 一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息
  • 第三种方式是使用OkHttp3ClientHttpRequestFactory方式,底层使用OkHttp访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息
  • RestTemplate默认是使用SimpleClientHttpRequestFactory,内部是调用jdk的HttpConnection,默认超时为-1

优点:连接池、超时时间设置、支持异步、请求和响应的编解码
缺点:依赖别的spring版块、参数传递不灵活

1.4缺点与新技术

org.springframework.web.client public class RestTemplate
extends InterceptingHttpAccessor
implements RestOperations
同步客户端执行HTTP请求,在底层HTTP客户端库(如JDK HttpURLConnection、Apache HttpComponents等)上公开一个简单的模板方法API。RestTemplate通过HTTP方法为常见场景提供了模板,此外还提供了支持不太常见情况的通用交换和执行方法。 RestTemplate通常用作共享组件。然而,它的配置不支持并发修改,因此它的配置通常是在启动时准备的。如果需要,您可以在启动时创建多个不同配置的RestTemplate实例。如果这些实例需要共享HTTP客户端资源,它们可以使用相同的底层ClientHttpRequestFactory。 注意:从5.0开始,这个类处于维护模式,只有对更改和错误的小请求才会被接受。请考虑使用org.springframework.web.react .client. webclient,它有更现代的API,支持同步、异步和流场景。

二、API 实践

RestTemplate最大的特色就是对各种网络请求方式做了包装,能极大的简化开发人员的工作量,下面我们以GET、POST、PUT、DELETE、文件上传与下载为例,分别介绍各个API的使用方式

2.1GET请求 

通过RestTemplate发送HTTP GET协议请求,经常使用到的方法有两个:

  • getForObject():返回值是HTTP协议的响应体
  • getForEntity():返回的是ResponseEntityResponseEntity是对HTTP响应的封装,除了包含响应体,还包含HTTP状态码、contentType、contentLength、Header等信息

Spring Boot环境下写一个单元测试用例,首先创建一个Api接口,然后编写单元测试进行服务测试。

不带参请求

不带参的get请求

@RestController
public class TestController {/*** 不带参的get请求* @return*/@RequestMapping(value = "testGet", method = RequestMethod.GET)public ResponseBean testGet(){ResponseBean result = new ResponseBean();result.setCode("200");result.setMsg("请求成功,方法:testGet");return result;}
}
public class ResponseBean {private String code;private String msg;省去getset方法 
}
@Autowired
private RestTemplate restTemplate;
/*** 单元测试(不带参的get请求)*/
@Test
public void testGet(){//请求地址String url = "http://localhost:8080/testGet";//发起请求,直接返回对象ResponseBean responseBean = restTemplate.getForObject(url, ResponseBean.class);System.out.println(responseBean.toString());
}

带参的get请求(使用占位符号传参)

@RestController
public class TestController {/*** 带参的get请求(restful风格)* @return*/@RequestMapping(value = "testGetByRestFul/{id}/{name}", method = RequestMethod.GET)public ResponseBean testGetByRestFul(@PathVariable(value = "id") String id, @PathVariable(value = "name") String name){ResponseBean result = new ResponseBean();result.setCode("200");result.setMsg("请求成功,方法:testGetByRestFul,请求参数id:" +  id + "请求参数name:" + name);return result;}
}
@Autowired
private RestTemplate restTemplate;/*** 单元测试(带参的get请求)*/
@Test
public void testGetByRestFul(){//请求地址String url = "http://localhost:8080/testGetByRestFul/{1}/{2}";//发起请求,直接返回对象(restful风格)ResponseBean responseBean = restTemplate.getForObject(url, ResponseBean.class, "001", "张三");System.out.println(responseBean.toString());
}

带参的get请求(restful风格)

@RestController
public class TestController {/*** 带参的get请求(使用占位符号传参)* @return*/@RequestMapping(value = "testGetByParam", method = RequestMethod.GET)public ResponseBean testGetByParam(@RequestParam("userName") String userName,@RequestParam("userPwd") String userPwd){ResponseBean result = new ResponseBean();result.setCode("200");result.setMsg("请求成功,方法:testGetByParam,请求参数userName:" +  userName + ",userPwd:" + userPwd);return result;}
}
@Autowired
private RestTemplate restTemplate;/*** 单元测试(带参的get请求)*/
@Test
public void testGetByParam(){//请求地址String url = "http://localhost:8080/testGetByParam?userName={userName}&userPwd={userPwd}";//请求参数Map<String, String> uriVariables = new HashMap<>();uriVariables.put("userName", "唐三藏");uriVariables.put("userPwd", "123456");//发起请求,直接返回对象(带参数请求)ResponseBean responseBean = restTemplate.getForObject(url, ResponseBean.class, uriVariables);System.out.println(responseBean.toString());
}

getForEntity使用示例

上面的所有的getForObject请求传参方法,getForEntity都可以使用,使用方法上也几乎是一致的,只是在返回结果接收的时候略有差别。

使用ResponseEntity<T> responseEntity来接收响应结果。用responseEntity.getBody()获取响应体。

 /*** 单元测试*/
@Test
public void testAllGet(){//请求地址String url = "http://localhost:8080/testGet";//发起请求,返回全部信息ResponseEntity<ResponseBean> response = restTemplate.getForEntity(url, ResponseBean.class);// 获取响应体System.out.println("HTTP 响应body:" + response.getBody().toString());// 以下是getForEntity比getForObject多出来的内容HttpStatus statusCode = response.getStatusCode();int statusCodeValue = response.getStatusCodeValue();HttpHeaders headers = response.getHeaders();System.out.println("HTTP 响应状态:" + statusCode);System.out.println("HTTP 响应状态码:" + statusCodeValue);System.out.println("HTTP Headers信息:" + headers);
}

header设置参数

//请求头
HttpHeaders headers = new HttpHeaders();
headers.add("token", "123456789");//封装请求头
HttpEntity<MultiValueMap<String, Object>> formEntity = new HttpEntity<>(headers);ResponseEntity<Map> exchange = restTemplate.exchange('请求的url', HttpMethod.GET, formEntity, Map.class);

2.2POST请求

其实POST请求方法和GET请求方法上大同小异,RestTemplatePOST请求也包含两个主要方法:

  • postForObject():返回body对象
  • postForEntity():返回全部的信息

模拟表单请求

模拟表单请求,post方法测试

@RestController
public class TestController {/*** 模拟表单请求,post方法测试* @return*/@RequestMapping(value = "testPostByForm", method = RequestMethod.POST)public ResponseBean testPostByForm(@RequestParam("userName") String userName,@RequestParam("userPwd") String userPwd){ResponseBean result = new ResponseBean();result.setCode("200");result.setMsg("请求成功,方法:testPostByForm,请求参数userName:" + userName + ",userPwd:" + userPwd);return result;}
}
@Autowired
private RestTemplate restTemplate;/*** 模拟表单提交,post请求*/
@Test
public void testPostByForm(){//请求地址String url = "http://localhost:8080/testPostByForm";// 请求头设置,x-www-form-urlencoded格式的数据HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);//提交参数设置MultiValueMap<String, String> map = new LinkedMultiValueMap<>();map.add("userName", "唐三藏");map.add("userPwd", "123456");// 组装请求体HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);//发起请求ResponseBean responseBean = restTemplate.postForObject(url, request, ResponseBean.class);System.out.println(responseBean.toString());
}

 模拟表单请求(传递对象)

模拟表单请求,post方法测试(对象接受)

@RestController
public class TestController {/*** 模拟表单请求,post方法测试* @param request* @return*/@RequestMapping(value = "testPostByFormAndObj", method = RequestMethod.POST)public ResponseBean testPostByForm(RequestBean request){ResponseBean result = new ResponseBean();result.setCode("200");result.setMsg("请求成功,方法:testPostByFormAndObj,请求参数:" + JSON.toJSONString(request));return result;}
}public class RequestBean {private String userName;private String userPwd;省去getset方法
}
@Autowired
private RestTemplate restTemplate;/*** 模拟表单提交,post请求*/
@Test
public void testPostByForm(){//请求地址String url = "http://localhost:8080/testPostByFormAndObj";// 请求头设置,x-www-form-urlencoded格式的数据HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);//提交参数设置MultiValueMap<String, String> map = new LinkedMultiValueMap<>();map.add("userName", "唐三藏");map.add("userPwd", "123456");// 组装请求体HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);//发起请求ResponseBean responseBean = restTemplate.postForObject(url, request, ResponseBean.class);System.out.println(responseBean.toString());
}

模拟JSON请求

模拟JSON请求,post方法测试

@RestController
public class TestController {/*** 模拟JSON请求,post方法测试* @param request* @return*/@RequestMapping(value = "testPostByJson", method = RequestMethod.POST)public ResponseBean testPostByJson(@RequestBody RequestBean request){ResponseBean result = new ResponseBean();result.setCode("200");result.setMsg("请求成功,方法:testPostByJson,请求参数:" + JSON.toJSONString(request));return result;}
}
@Autowired
private RestTemplate restTemplate;
/*** 模拟JSON提交,post请求*/
@Test
public void testPostByJson(){//请求地址String url = "http://localhost:8080/testPostByJson";//入参RequestBean request = new RequestBean();request.setUserName("唐三藏");request.setUserPwd("123456789");//发送post请求,并打印结果,以String类型接收响应结果JSON字符串ResponseBean responseBean = restTemplate.postForObject(url, request, ResponseBean.class);System.out.println(responseBean.toString());
}

 模拟页面重定向

模拟页面重定向,post请求

@Controller
public class LoginController {/*** 重定向* @param request* @return*/@RequestMapping(value = "testPostByLocation", method = RequestMethod.POST)public String testPostByLocation(@RequestBody RequestBean request){return "redirect:index.html";}
}
@Autowired
private RestTemplate restTemplate;
/*** 重定向,post请求*/
@Test
public void testPostByLocation(){//请求地址String url = "http://localhost:8080/testPostByLocation";//入参RequestBean request = new RequestBean();request.setUserName("唐三藏");request.setUserPwd("123456789");//用于提交完成数据之后的页面跳转,返回跳转urlURI uri = restTemplate.postForLocation(url, request);System.out.println(uri.toString());
}输出结果如下:
http://localhost:8080/index.html

2.3PUT请求

put请求方法,可能很多人都没用过,它指的是修改一个已经存在的资源或者插入资源,该方法会向URL代表的资源发送一个HTTP PUT方法请求,示例如下

@RestController
public class TestController {/*** 模拟JSON请求,put方法测试* @param request* @return*/@RequestMapping(value = "testPutByJson", method = RequestMethod.PUT)public void testPutByJson(@RequestBody RequestBean request){System.out.println("请求成功,方法:testPutByJson,请求参数:" + JSON.toJSONString(request));}
}
@Autowired
private RestTemplate restTemplate;
/*** 模拟JSON提交,put请求*/
@Test
public void testPutByJson(){//请求地址String url = "http://localhost:8080/testPutByJson";//入参RequestBean request = new RequestBean();request.setUserName("唐三藏");request.setUserPwd("123456789");//模拟JSON提交,put请求restTemplate.put(url, request);
}

2.4DELETE请求

与之对应的还有delete方法协议,表示删除一个已经存在的资源,该方法会向URL代表的资源发送一个HTTP DELETE方法请求。

@RestController
public class TestController {/*** 模拟JSON请求,delete方法测试* @return*/@RequestMapping(value = "testDeleteByJson", method = RequestMethod.DELETE)public void testDeleteByJson(){System.out.println("请求成功,方法:testDeleteByJson");}
}
@Autowired
private RestTemplate restTemplate;
/*** 模拟JSON提交,delete请求*/
@Test
public void testDeleteByJson(){//请求地址String url = "http://localhost:8080/testDeleteByJson";//模拟JSON提交,delete请求restTemplate.delete(url);
}

2.5 通用请求方法exchange方法

如果以上方法还不满足你的要求。在RestTemplate工具类里面,还有一个exchange通用协议请求方法,它可以发送GET、POST、DELETE、PUT、OPTIONS、PATCH等等HTTP方法请求

2.6通过服务名调用

简介

Spring Cloud中,通过服务名称访问其他服务通常需要使用@LoadBalancedRestTemplate,可以使用服务名(service ID)来代替具体的URL

@Configuration
public class Config 
{@LoadBalanced@Beanpublic RestTemplate restTemplate() {SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();// 设置超时requestFactory.setConnectTimeout(60 * 1000);requestFactory.setReadTimeout(60 * 1000);//利用复杂构造器可以实现超时设置,内部实际实现为 HttpClientRestTemplate restTemplate = new RestTemplate(requestFactory);return restTemplate ;}
}

上面的代码定义了一个 RestTemplate bean,并使用@LoadBalanced注解来开启负载均衡。这样,就可以在 应用中自动注入RestTemplate,然后使用服务名称来发送请求,即可通过 http://SERVICE-NAME/quest-path 访问对应名称的微服务

注意:这种方法需要服务被注册到服务发现组件(如EurekaNacosConsul等)。这样,应用才能找到服务名对应的实际网络位置。

@LoadBalanced作用

@LoadBalanced 是 Netflix 的 ribbon 中的一个负载均衡的注解,并完成以下工作:

  • 从负载均衡器中选一个对应的服务实例,所有的服务名实例都放在负载均衡器中的serverlist中;
  • 从挑选的实例中去请求内容;
  • 由服务名转为真正使用的ip地址;

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

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

相关文章

kali工具----网络映射器(Network Mapper)系统指纹

系统指纹识别 现在一些便携式计算机操作系统使用指纹识别来验证密码进行登录。指纹识别是识别系统的一个典型模式&#xff0c;包括指纹图像获取、处理、特征提取和对等模块。如果要做渗透测试&#xff0c;需要了解要渗透测试的操作系统的类型才可以。本节将介绍使用Nmap工具测试…

【OTA】STM32-OTA升级——持续更新

【OTA】STM32-OTA升级——持续更新 文章目录 前言一、ymodem串口协议1、Ymodem 协议2、PC3、蓝牙4、WIFI云平台 二、UDS车载协议1.UDS协议 总结 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、ymodem串口协议 1、Ymodem 协议 STM32 Ymodem …

【第三十篇】并发插件 turbo intruder 安装及使用教程

文章目录 安装使用本篇主要介绍turbo intruder的两种安装方式及使用教程。 安装 1、在BurpSuite的扩展模块的BAPP商店中找到turbo intruder,点击安装即可使用: 2、若在BurpSuite中无法直接安装,可手动添加该插件。 具体操作: 进入Github中安装: https://github.com/Po…

代码随想录算法训练营三刷day53 | 动态规划之子序列 1143.最长公共子序列 1035.不相交的线 53. 最大子序和

day53 1143.最长公共子序列1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp数组 1035.不相交的线53. 最大子序和1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义2.确定递推公式3.dp数组如…

FireProx:一款功能强大的AWS API网关管理与IP地址轮换代理工具

关于FireProx FireProx是一款功能强大的AWS API网关安全管理工具&#xff0c;该工具可以帮助广大研究人员创建实现唯一IP地址轮换的实时HTTP转发代理。 在发送网络请求或进行网络交互时&#xff0c;实现源IP地址轮换是一个非常复杂的过程&#xff0c;虽然社区中也有相关的工具…

【STL详解 —— stack和queue的介绍及使用】

STL详解 —— stack和queue的介绍及使用 stackstack的定义方式stack的使用 queuequeue的定义方式queue的使用 stack stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其只能从容器的一端进行元素的插入与提取操作。 stack的定义方式 首…

前端三剑客 —— JavaScript (第六节)

目录 内容回顾 BOM编程 DOM编程* document对象 document对象的属性 document对象的方法 DOM对象节点 操作DOM对象内容 操作DOM对象的属性 --- DOM对象.属性名称 --- DOM对象[属性名称] --- 调用系统API &#xff08;Application Program interface&#xff09;&#…

Linux登录访问限制

Linux系统下&#xff0c;用户密码的有效期可以通过编辑/etc/login.defs文件控制&#xff1b;密码复杂度规则设定需要通过/etc/pam.d/system-auth文件控制&#xff1b;登录失败次数限制通常由/etc/pam.d/login文件限制&#xff0c;可使用pam_tally2模块进行设置。 Linux系统下的…

爬虫 | 网易新闻热点数据的获取与保存

Hi&#xff0c;大家好&#xff0c;我是半亩花海。本项目是一个简单的网络爬虫&#xff0c;用于从网易新闻的热点新闻列表中提取标题和对应的链接&#xff0c;并将提取到的数据保存到一个 CSV 文件中。 目录 一、技术栈 二、功能说明 三、注意事项 四、代码解析 1. 导入所需…

Playwright安装和基本使用(ui/web自动化)

1.简介 Playwright是2021年微软开源的一个项目「playwright-python」。针对 Python 语言的纯自动化工具&#xff0c;它可以通过单个API自动执行 Chromium&#xff0c;Firefox 和 WebKit 浏览器&#xff0c;同时支持以无头模式、有头模式运行。 Playwright&#xff08;Git&…

springboot汽车企业公司网站的系统设计ssm-java

框架&#xff1a;SSM/springboot都有 jdk版本&#xff1a;1.8 及以上 ide工具&#xff1a;IDEA 或者eclipse 数据库: mysql 编程语言: java 前端&#xff1a;layuibootstrapjsp 详细技术&#xff1a;HTMLCSSJSjspspringmvcmybatisMYSQLMAVENtomcat 开发工具 IntelliJ IDEA: 一…

【学习】软件测试人员使用Loadrunner进行性能测试的优势

在软件测试领域&#xff0c;性能测试是一项至关重要的环节&#xff0c;它关乎到软件系统的稳定性和用户体验。而在这其中&#xff0c;Loadrunner作为一款久经考验的性能测试工具&#xff0c;凭借其独特的优势&#xff0c;成为了众多企业和开发者眼中的“得力助手”。 首先&…

1036: 寻找整数序列的主元素

解法&#xff1a; #include<iostream> #include<vector> #include<algorithm> using namespace std; int main() {int n;cin >> n;vector<int> arr(n);vector<int> tong(1000);for (auto& x : arr) {cin >> x;tong[x];}int pma…

Guava里一些比较常用的工具

随着java版本的更新提供了越来越多的语法和工具来简化日常开发&#xff0c;但是我们一般用的比较早的版本所以体验不到。这时就用到了guava这个包。guava提供了很多方便的工具方法&#xff0c;solar框架就依赖了guava的16.0.1版本&#xff0c;这里稍微介绍下。 一、集合工具类…

vue3 uniapp微信登录

根据最新的微信小程序官方的规定&#xff0c;uniapp中的uni.getUserInfo方法不再返回用户头像和昵称、以及手机号 首先&#xff0c;需获取appID&#xff0c;appSecret&#xff0c;如下图 先调用uni.getUserInfo方法获取code&#xff0c;然后调用后台的api&#xff0c;传入code&…

大模型项目整体规划、技术选型和案例分析经验分享

1 项目整体规划 1.1 明确场景 toB or toC&#xff08;面向企业还是面向消费者&#xff09; toB&#xff08;面向企业&#xff09;&#xff1a;指的是产品或服务主要面向其他企业或组织。这类产品通常需要解决特定的商业问题&#xff0c;强调效率和集成性&#xff0c;并且可能需…

什么是 MVVM、mvc 模型

mvc模型 MVC: MVC 即 model-view-controller&#xff08;模型-视图-控制器)是项目的一种分层架构思想&#xff0c;它把复杂的业务逻辑&#xff0c; 抽离为职能单一的小模块&#xff0c;每个模块看似相互独立&#xff0c;其实又各自有相互依赖关系。它的好处是&#xff1a;保证了…

如何选择最好的数据恢复软件?最佳免费数据恢复软件集

丢失或删除文件并不意味着它已从您的设备中永久删除。 下次您不小心删除或丢失文件时&#xff0c;请不要惊慌&#xff0c;丢失的文件仍然可以恢复&#xff0c;但前提是您迅速采取行动。 驱动器具有用于存储文件的目录。删除数据需要很长时间&#xff0c;因此您删除的任何文件都…

BetterZip解锁文件处理新境界

在数字化时代的浪潮中&#xff0c;文件处理成为了我们日常生活和工作中不可或缺的一部分。压缩软件&#xff0c;作为文件处理的得力助手&#xff0c;以其出色的压缩性能、便捷的操作体验以及强大的文件管理能力&#xff0c;赢得了广大用户的青睐。在众多压缩软件中&#xff0c;…

热词解析| 制造企业如何跟上新质生产力建设步伐【触想智能】

回顾3月份的网络热词&#xff0c;「新质生产力」在各大平台霸榜刷屏&#xff0c;并且受到两会政府工作报告的频繁聚焦。究竟何为新质生产力?以及&#xff0c;传统制造企业如何加速融入这场火热的现代化产业革新浪潮之中? 图源| 纪录片《加快形成新质生产力》 1、什么是新质生…