RestTemplate 介绍和用法
RestTemplate 简介
RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。RestTemplate 继承自 InterceptingHttpAccessor 并且实现了 RestOperations 接口,其中 RestOperations 接口定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现。接下来我们就来看看这些操作方法的使用。
导入坐标:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
GET 请求
getForEntity
既然 RestTemplate 发送的是 HTTP 请求,那么在响应的数据中必然也有响应头,如果开发者需要获取响应头的话,那么就需要使用 getForEntity 来发送 HTTP 请求,此时返回的对象是一个 ResponseEntity 的实例。这个实例中包含了响应数据以及响应头。例如,在 provider 中提供一个 HelloController 接口,HelloController 接口中定义一个 sayHello 的方法,如下:
@RestController
public class UseHelloController {
@Autowired
DiscoveryClient discoveryClient;
@Autowired
RestTemplate restTemplate;
@GetMapping("/hello")
public String hello(String name) {
List<ServiceInstance> list = discoveryClient.getInstances("provider");
ServiceInstance instance = list.get(0);
String host = instance.getHost();
int port = instance.getPort();
String url = "http://" + host + ":" + port + "/hello?name={1}";
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class, name);
StringBuffer sb = new StringBuffer();
HttpStatus statusCode = responseEntity.getStatusCode();
String body = responseEntity.getBody();
sb.append("statusCode:")
.append(statusCode)
.append("</br>")
.append("body:")
.append(body)
.append("</br>");
HttpHeaders headers = responseEntity.getHeaders();
Set<String> keySet = headers.keySet();
for (String s : keySet) {
sb.append(s)
.append(":")
.append(headers.get(s))
.append("</br>");
}
return sb.toString();
}
}
当然,这里参数的传递除了这一种方式之外,还有另外两种方式,也就是 getForEntity 方法的另外两个重载方法。
第一个是占位符不使用数字,而是使用参数的 key,同时将参数放入到一个 map 中。map 中的 key 和占位符的 key 相对应,map 中的 value 就是参数的具体值,例如还是上面的请求,利用 map 来传递参数,请求方式如下:
Map<String, Object> map = new HashMap<>();
String url = "http://" + host + ":" + port + "/hello?name={name}";
map.put("name", name);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class, map);
String url = "http://" + host + ":" + port + "/hello?name="+ URLEncoder.encode(name,"UTF-8");
URI uri = URI.create(url);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
但需要注意的是,这种传参方式,参数如果是中文的话,需要对参数进行编码,使用 URLEncoder.encode
方法来实现
getForObject
getForObject 方法和 getForEntity 方法类似,getForObject 方法也有三个重载的方法,参数和 getForEntity 一样,因此这里我就不重复介绍参数了,这里主要说下 getForObject 和 getForEntity 的差异,这两个的差异主要体现在返回值的差异上, getForObject 的返回值就是服务提供者返回的数据,使用 getForObject 无法获取到响应头。例如,还是上面的请求,利用 getForObject 来发送 HTTP 请求,结果如下:
String url = "http://" + host + ":" + port + "/hello?name=" + URLEncoder.encode(name, "UTF-8");
URI uri = URI.create(url);
String s = restTemplate.getForObject(uri, String.class);
注意,这里返回的 s 就是 provider 的返回值,如果开发者只关心 provider 的返回值,并不关系 HTTP 请求的响应头,那么可以使用该方法。
POST 请求
和 GET 请求相比,RestTemplate 中的 POST 请求多了一个类型的方法,如下:
可以看到,post 请求的方法类型除了 postForEntity 和 postForObject 之外,还有一个 postForLocation。这里的方法类型虽然有三种,但是这三种方法重载的参数基本是一样的,因此这里我还是以 postForEntity 方法为例,来剖析三个重载方法的用法,最后再重点说下 postForLocation 方法。
postForEntity
在 POST 请求中,参数的传递可以是 key/value 的形式,也可以是 JSON 数据,分别来看:
- 传递 key/value 形式的参数
首先在 provider 的 HelloController 类中再添加一个 POST 请求的接口,如下:
@PostMapping("/hello2")
public String sayHello2(String name) {
return "Hello " + name + " !";
}
然后在 consumer 中添加相应的方法去访问,如下:
@GetMapping("/hello5")
public String hello5(String name) {
List<ServiceInstance> list = discoveryClient.getInstances("provider");
ServiceInstance instance = list.get(0);
String host = instance.getHost();
int port = instance.getPort();
String url = "http://" + host + ":" + port + "/hello2";
MultiValueMap map = new LinkedMultiValueMap();
map.add("name", name);
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, map, String.class);
return responseEntity.getBody();
}
在这里, postForEntity 方法第一个参数是请求地址,第二个参数 map 对象中存放着请求参数 key/value,第三个参数则是返回的数据类型。当然这里的第一个参数 url 地址也可以换成一个 Uri 对象,效果是一样的。这种方式传递的参数是以 key/value 形式传递的,在 post 请求中,也可以按照 get 请求的方式去传递 key/value 形式的参数,传递方式和 get 请求的传参方式基本一致,例如下面这样:
@GetMapping("/hello6")
public String hello6(String name) {
List<ServiceInstance> list = discoveryClient.getInstances("provider");
ServiceInstance instance = list.get(0);
String host = instance.getHost();
int port = instance.getPort();
String url = "http://" + host + ":" + port + "/hello2?name={1}";
ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, null, String.class,name);
return responseEntity.getBody();
}
此时第二个参数可以直接传一个 null。
- 传递 JSON 数据
上面介绍的是 post 请求传递 key/value 形式的参数,post 请求也可以直接传递 json 数据,在 post 请求中,可以自动将一个对象转换成 json 进行传输,数据到达 provider 之后,再被转换为一个对象。具体操作步骤如下:
首先在 RestTemplate 项目中创建一个新的maven项目,叫做 commons ,然后在 commons 中创建一个 User 对象,如下:
public class User {
private String username;
private String address;
//省略getter/setter
}
然后分别在 provider 和 consumer 的 pom.xml 文件中添加对 commons 模块的依赖,如下:
<dependency>
<groupId>com.justdojava</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
这样,在 provider 和 consumer 中就都能使用 User 对象了。首先在 provider 中创建一个添加用户的接口,如下:
@Controller
@ResponseBody
public class UserController {
@PostMapping("/user")
public User hello(@RequestBody User user) {
return user;
}
}
这里的接口很简单,只需要将用户传来的 User 对象再原封不动地返回去就行了,然后在 consumer 中添加一个接口来测试这个接口,如下:
@GetMapping("/hello7")
public User hello7() {
List<ServiceInstance> list = discoveryClient.getInstances("provider");
ServiceInstance instance = list.get(0);
String host = instance.getHost();
int port = instance.getPort();
String url = "http://" + host + ":" + port + "/user";
User u1 = new User();
u1.setUsername("牧码小子");
u1.setAddress("深圳");
ResponseEntity<User> responseEntity = restTemplate.postForEntity(url, u1, User.class);
return responseEntity.getBody();
}
看到这段代码有人要问了,这不和前面的一样吗?是的,唯一的区别就是第二个参数的类型不同,这个参数如果是一个 MultiValueMap 的实例,则以 key/value 的形式发送,如果是一个普通对象,则会被转成 json 发送。
postForObject
postForObject 和 postForEntity 基本一致,就是返回类型不同而已,这里不再赘述。
postForLocation
postForLocation 方法的返回值是一个 Uri 对象,因为 POST 请求一般用来添加数据,有的时候需要将刚刚添加成功的数据的 URL 返回来,此时就可以使用这个方法,一个常见的使用场景如用户注册功能,用户注册成功之后,可能就自动跳转到登录页面了,此时就可以使用该方法。例如在 provider 中提供一个用户注册接口,再提供一个用户登录接口,如下:
@RequestMapping("/register")
public String register(User user) throws UnsupportedEncodingException {
return "redirect:/loginPage?username=" + URLEncoder.encode(user.getUsername(),"UTF-8") + "&address=" + URLEncoder.encode(user.getAddress(),"UTF-8");
}
@GetMapping("/loginPage")
@ResponseBody
public String loginPage(User user) {
return "loginPage:" + user.getUsername() + ":" + user.getAddress();
}
这里一个注册接口,一个是登录页面,不过这里的登录页面我就简单用一个字符串代替了。然后在 consumer 中来调用注册接口,如下:
@GetMapping("/hello8")
public String hello8() {
List<ServiceInstance> list = discoveryClient.getInstances("provider");
ServiceInstance instance = list.get(0);
String host = instance.getHost();
int port = instance.getPort();
String url = "http://" + host + ":" + port + "/register";
MultiValueMap map = new LinkedMultiValueMap();
map.add("username", "牧码小子");
map.add("address", "深圳");
URI uri = restTemplate.postForLocation(url, map);
String s = restTemplate.getForObject(uri, String.class);
return s;
}
代码是我写的demo 只需要看restTemplate 那一块的代码就可以了
RestTemplate 介绍和用法的更多相关文章
- oc-12-NSString 类简单介绍及用法
// 11-[掌握]NSString 类简单介绍及用法 #import <Foundation/Foundation.h> int main(int argc, const char * ...
- WorkFlow介绍及用法
WorkFlow介绍及用法 说起workflow大家肯定都不陌生,这里简单介绍一下salesforce中什么情况下使用workflow. 当你分配许多任务,定期发送电子邮件,记录修改时,可以通过自动配 ...
- Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法
Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法 1. BeanFactory BeanFactory,以Factory结尾,表示它是一个工厂类(接口),用于 ...
- vue第四单元(初识vue-在页面中直接引入vue框架-学习使用vue语法-vue的指令-介绍data用法-methods用法)
第四单元(初识vue-在页面中直接引入vue框架-学习使用vue语法-vue的指令-介绍data用法-methods用法) #课程目标 了解 vue 框架的特点 掌握创建 vue 实例 掌握 data ...
- ServletContext介绍和用法总结
ServletContext介绍和用法总结 学习总结 一.ServletContext 介绍 1. 概念 2. 作用 3. 获取 3.1 在实现类中获取 3.2 在 Spring 容器中获取 二.Se ...
- Spring RestTemplate介绍
http://www.cnblogs.com/rollenholt/p/3894117.html RestTemplate 这篇文章打算介绍一下Spring的RestTemplate.我这边以前设计到 ...
- 08_android入门_android-async-http开源项目介绍及用法
android-async-http开源项目可以是我们轻松的获取网络数据或者向server发送数据.使用起来很easy,关于android-async-http开源项目的介绍内容来自于官方:http: ...
- JMS学习篇《一》ActiveMQ消息中间件的简单介绍与用法-概念篇
原创说明:本篇博文为本人原创作品,转载请注明出处 1.何为消息中间件 消息中间件是一种在分布式应用中互相交换信息的一种技术,常见的成熟消息中间件有:RabbitMQ.SonicMQ,activeMQ. ...
- Cookie、Session登陆验证相关介绍和用法
一.Cookie和Session 首先.HTTP协议是无状态的:所谓的无状态是指每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应直接影响,也不会直接 ...
- springboot系列十二、springboot集成RestTemplate及常见用法
一.背景介绍 在微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端.我们可以使用JDK原生的URLConnection.Apache的Http Client.N ...
随机推荐
- 无监督多视角行人检测 Unsupervised Multi-view Pedestrian Detection
无监督多视角行人检测 Unsupervised Multi-view Pedestrian Detection 论文url:https://arxiv.org/abs/2305.12457 论文简述 ...
- Python3学习--正则表达式
import rer = re.match("Chen\d+","Chen123ronghua123")r = re.match(".+", ...
- c# webapi 自定义返回数据
前言 webapi呢,我们创建的时候我给我们5个方法:get get(data)put post delete. 很明显,get,get(data)是用来获取,post用来修改数据的,put,dele ...
- mac版本vscode窗口崩溃crashed
1.截图 出现时机 当安装依赖的时候大概率会出现,甚至安装一次依赖会出现几次 解决 具体原因未知 重新启动电脑以及退出软件都不能解决 去官网重新下载,重新安装问题解决
- 小米电商 Apache Dubbo-go 微服务实践
简介:2021 年是小米中国区电商部门变动调整较大的一年,小米中国区早期电商.服务体系建立在 Go 语言构建的微服务体系之上,由内部自研的 Go 语言微服务框架 koala 支撑起数以千计的微服务应 ...
- 创新推出 | Serverless 场景排查问题利器:函数实例命令行操作
简介: 实例命令行功能的推出希望能消除用户使用 Serverless 的"最后一公里",直接将真实的函数运行环境展现给用户,此后 Serverless 将不再是一个"黑 ...
- KubeDL 0.4.0 - Kubernetes AI 模型版本管理与追踪
简介:欢迎更多的用户试用 KubeDL,并向我们提出宝贵的意见,也期待有更多的开发者关注以及参与 KubeDL 社区的建设! 作者:陈裘凯( 求索) 前言 KubeDL 是阿里开源的基于 Kuber ...
- [GPT] export, export default, import, module.exports, require
ES6 规范:export 和 import 配对 import 的 {} 大括号里面指定要从其他模块导入的变量名, 如果 export 命令没有写 default,那么 import {} 大括号里 ...
- [Go] golang 执行 Linux 系统 command
执行系统 shell 命令示例: fileDir := "files/"out, err := exec.Command("sh", "-c" ...
- 修复 WPF 安装 WindowsAppSDK 库构建失败 NETSDK1082 和 NETSDK1112 找不到 win10-arm 失败
通过在 WPF 项目上安装 WindowsAppSDK 库,可以让 WPF 使用上 Win10 及以上版本提供的 Windows Runtime 强大的 API 集和使用上更多的黑科技.本文记录在安装 ...