spring restTemplate使用方法

https://github.com/lenve/SimpleSpringCloud/tree/master/RestTemplate在Spring Cloud中服务的发现与消费一文中,当我们从服务消费端去调用服务提供者的服务的时候,使用了一个很好用的对象,叫做RestTemplate,当时我们只使用了RestTemplate中最简单的一个功能getForEntity发起了一个get请求去调用服务端的数据,同时,我们还通过配置@LoadBalanced注解开启客户端负载均衡,RestTemplate的功能不可谓不强大,那么今天我们就来详细的看一下RestTemplate中几种常见请求方法的使用。

本文是Spring Cloud系列的第六篇文章,了解前五篇文章的内容有助于更好的理解本文:

1.使用Spring Cloud搭建服务注册中心
2.使用Spring Cloud搭建高可用服务注册中心
3.Spring Cloud中服务的发现与消费
4.Eureka中的核心概念
5.什么是客户端负载均衡

本文主要从以下四个方面来看RestTemplate的使用:

GET请求
POST请求
PUT请求
DELETE请求
OK,开始吧。

环境搭建
首先我们要搭建一个测试环境,方便我们一会验证相应的API。
服务注册中心我就直接使用前文(使用Spring Cloud搭建服务注册中心)中创建的服务注册中心。
服务提供者和服务消费者我创建在一个maven工程中,如果小伙伴对IntelliJ IDEA中创建maven多模块项目还不了解的话,可以参考IntelliJ IDEA中创建Web聚合项目(Maven多模块项目)。创建好的maven项目如下图所示:

 

其中commons是一个公共模块,是一个普通的JavaSE工程,我们一会主要将实体类写在这个模块中,provider和consumer是两个spring boot项目,provider将扮演服务提供者的角色,consumer扮演服务消费者的角色。

commons模块主要用来提供实体类,内容如下:

 

然后在provider和consumer模块中添加对commons的依赖,依赖代码如下:

<dependency>
<groupId>org.sang</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
1
provider和consumer的开发小伙伴们可以参考使用Spring Cloud搭建服务注册中心和Spring Cloud中服务的发现与消费,我这里就不再赘述了。下文中我只列出provider和consumer的核心代码,文末可以下载源码。

GET请求
在RestTemplate中,发送一个GET请求,我们可以通过如下两种方式:

第一种:getForEntity
getForEntity方法的返回值是一个ResponseEntity<T>,ResponseEntity<T>是Spring对HTTP请求响应的封装,包括了几个重要的元素,如响应码、contentType、contentLength、响应消息体等。比如下面一个例子:

@RequestMapping("/gethello")
public String getHello() {
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class);
String body = responseEntity.getBody();
HttpStatus statusCode = responseEntity.getStatusCode();
int statusCodeValue = responseEntity.getStatusCodeValue();
HttpHeaders headers = responseEntity.getHeaders();
StringBuffer result = new StringBuffer();
result.append("responseEntity.getBody():").append(body).append("<hr>")
.append("responseEntity.getStatusCode():").append(statusCode).append("<hr>")
.append("responseEntity.getStatusCodeValue():").append(statusCodeValue).append("<hr>")
.append("responseEntity.getHeaders():").append(headers).append("<hr>");
return result.toString();
}
1
关于这段代码,我说如下几点:

getForEntity的第一个参数为我要调用的服务的地址,这里我调用了服务提供者提供的/hello接口,注意这里是通过服务名调用而不是服务地址,如果写成服务地址就没法实现客户端负载均衡了。
getForEntity第二个参数String.class表示我希望返回的body类型是String
拿到返回结果之后,将返回结果遍历打印出来
最终显示结果如下:

 

有时候我在调用服务提供者提供的接口时,可能需要传递参数,有两种不同的方式,如下:

@RequestMapping("/sayhello")
public String sayHello() {
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/sayhello?name={1}", String.class, "张三");
return responseEntity.getBody();
}
@RequestMapping("/sayhello2")
public String sayHello2() {
Map<String, String> map = new HashMap<>();
map.put("name", "李四");
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/sayhello?name={name}", String.class, map);
return responseEntity.getBody();
}
1
可以用一个数字做占位符,最后是一个可变长度的参数,来一一替换前面的占位符
也可以前面使用name={name}这种形式,最后一个参数是一个map,map的key即为前边占位符的名字,map的value为参数值
第一个调用地址也可以是一个URI而不是字符串,这个时候我们构建一个URI即可,参数神马的都包含在URI中了,如下:

@RequestMapping("/sayhello3")
public String sayHello3() {
UriComponents uriComponents = UriComponentsBuilder.fromUriString("http://HELLO-SERVICE/sayhello?name={name}").build().expand("王五").encode();
URI uri = uriComponents.toUri();
ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
return responseEntity.getBody();
}
1
通过Spring中提供的UriComponents来构建Uri即可。

当然,服务提供者不仅可以返回String,也可以返回一个自定义类型的对象,比如我的服务提供者中有如下方法:

@RequestMapping(value = "/getbook1", method = RequestMethod.GET)
public Book book1() {
return new Book("三国演义", 90, "罗贯中", "花城出版社");
}
1
对于该方法我可以在服务消费者中通过如下方式来调用:

@RequestMapping("/book1")
public Book book1() {
ResponseEntity<Book> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/getbook1", Book.class);
return responseEntity.getBody();
}
1
运行结果如下:

 

第二种:getForObject
getForObject函数实际上是对getForEntity函数的进一步封装,如果你只关注返回的消息体的内容,对其他信息都不关注,此时可以使用getForObject,举一个简单的例子,如下:

@RequestMapping("/book2")
public Book book2() {
Book book = restTemplate.getForObject("http://HELLO-SERVICE/getbook1", Book.class);
return book;
}
1
getForObject也有几个重载方法,如下:

 

这几个重载方法参数的含义和getForEntity一致,我就不再赘述了。

POST请求
在RestTemplate中,POST请求可以通过如下三个方法来发起:

第一种:postForEntity
该方法和get请求中的getForEntity方法类似,如下例子:

@RequestMapping("/book3")
public Book book3() {
Book book = new Book();
book.setName("红楼梦");
ResponseEntity<Book> responseEntity = restTemplate.postForEntity("http://HELLO-SERVICE/getbook2", book, Book.class);
return responseEntity.getBody();
}
1
方法的第一参数表示要调用的服务的地址
方法的第二个参数表示上传的参数
方法的第三个参数表示返回的消息体的数据类型
我这里创建了一个Book对象,这个Book对象只有name属性有值,将之传递到服务提供者那里去,服务提供者代码如下:

@RequestMapping(value = "/getbook2", method = RequestMethod.POST)
public Book book2(@RequestBody Book book) {
System.out.println(book.getName());
book.setPrice(33);
book.setAuthor("曹雪芹");
book.setPublisher("人民文学出版社");
return book;
}
1
服务提供者接收到服务消费者传来的参数book,给其他属性设置上值再返回,调用结果如下:

 

postForEntity的其他重载方法如下:

 

这些方法的参数含义和getForEntity参数的含义一致,不再赘述。

第二种:postForObject
如果你只关注,返回的消息体,可以直接使用postForObject。用法和getForObject一致。

第三种:postForLocation
postForLocation也是提交新资源,提交成功之后,返回新资源的URI,postForLocation的参数和前面两种的参数基本一致,只不过该方法的返回值为Uri,这个只需要服务提供者返回一个Uri即可,该Uri表示新资源的位置。

PUT请求
在RestTemplate中,PUT请求可以通过put方法调用,put方法的参数和前面介绍的postForEntity方法的参数基本一致,只是put方法没有返回值而已。举一个简单的例子,如下:

@RequestMapping("/put")
public void put() {
Book book = new Book();
book.setName("红楼梦");
restTemplate.put("http://HELLO-SERVICE/getbook3/{1}", book, 99);
}
1
book对象是我要提交的参数,最后的99用来替换前面的占位符{1}

DELETE请求
delete请求我们可以通过delete方法调用来实现,如下例子:

@RequestMapping("/delete")
public void delete() {
restTemplate.delete("http://HELLO-SERVICE/getbook4/{1}", 100);
}
1
delete方法也有几个重载的方法,不过重载的参数和前面基本一致,不赘述。
---------------------
作者:_江南一点雨
来源:CSDN
原文:https://blog.csdn.net/u012702547/article/details/77917939/
版权声明:本文为博主原创文章,转载请附上博文链接!

转载于:https://www.cnblogs.com/CHWLearningNotes/p/10369623.html

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

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

相关文章

打印菱形星号组合C程序

#include "stdio.h" #define N 9 //数组的行列数 int main(){char str[N][N]{0}; //例子,行列数应该是奇数int i,j;for(i0;i<N;i)for(j0;j<N;j)str[i][j] ;//先全部设为空格//在特定位置写入*号for(i0;i<N;i)for(j0;j<N;j){if(i0 || iN…

程序员的十层楼(11层)

第11层 上帝 看了上面的小标题&#xff0c;你可能会觉得奇怪&#xff0c;这篇文章不是讲“程序员的十层楼”吗&#xff1f;怎么冒出了第11层来了&#xff1f; 其实这并不矛盾&#xff0c;程序员确实只有十层楼&#xff0c;因为爬到第11层时&#xff0c;已经变成上帝&#xff0c…

函数局部变量和函数的参数在栈中的布局

#include <stdio.h> #include <iostream>using namespace std; void func(int p1, int p2, int p3) {int a p1;int b p2;int c p3;std::cout << "函数参数入栈顺序(栈在内存中向上伸长):从右到左" << std::endl;std::cout << &quo…

经验:Windows To Go准备工作

如果您准备使用USB设备带着您的移动Windows的话&#xff0c;您需要做好准备。从开发预览版到正式版&#xff0c;我也一直关注着Windows Go To这个新功能&#xff0c;所以&#xff0c;总结了些经验&#xff0c;分享给大家&#xff0c;希望能够帮助到大家&#xff0c;或者减少您的…

图表相同数据会自动合并问题(finereport)

finereport中&#xff0c;对于图表的操作&#xff0c;当遇到需要显示多个重复分类下的多个值时&#xff0c;由于自动合并相同数据&#xff0c;无法达到效果反复查询手册无果后&#xff0c;困扰好久&#xff0c;终想到了一个解决的办法&#xff1a;1、给查询的数据添加个列序号&…

简单的C语言程序合集

输出九九乘法表1 #include <stdio.h>2 int main()3 {4 int i,j;5 for(i1;i<9;)6 {7 for(j1;j<9;j)8 {9 if(i>j)10 {11 printf("%d*%d%d ",j,i,j*i);12 }13…

C#中读取“已注册的文件类型”的图标及读取指定文件图标的方法 (转)

usingSystem;usingSystem.IO;usingSystem.Drawing;usingMicrosoft.Win32;usingSystem.Runtime.InteropServices;namespaceGetIconDemo { ///<summary>///提供从操作系统读取图标的方法 ///</summary>publicclassGetSystemIcon { ///<summary>///依…

Redis基础知识点

Redis基础知识点&#xff1a; 1、Redis 采用的是基于内存的单进程单线程模型的 key-value 数据库。 2、默认16个数据库&#xff0c;类似数组下表从 0 开始&#xff0c;初始默认使用零号库。 select 0~15 命令用于在 0 ~ 15 号库之间进行切换 3、dbsize 命令查看当前数据库的 …

关于SQLSERVER的全文目录跟全文索引的区别

很久没有写随笔了&#xff0c;本来之前想写一篇关于SQLSERVER全文索引的随笔&#xff0c;可惜没有时间&#xff0c;一直拖到现在才有时间写&#xff0c;不好意思让各位久等了~ 先介绍一下SQLSERVER中的存储类对象&#xff0c;哈哈&#xff0c;先介绍一下概念嘛&#xff0c;让新…

安装rlwrap 的简单方法

1. 下载安装 epel包 rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 2. 安装rlwrap yum install rlwrap -y 然后进入oracle 就可以 正常的上下键进行功能切换了 注意需要使用命令 rlwrap sqlplus / as sysdba 转载于:https://www.cnblogs.…

简单的C语言程序合集-2

输入一个整数n&#xff0c;求从1到n这n个整数的十进制表示中1出现的次数。&#xff08;google面试题&#xff09; #include <stdio.h>int main(){int n, N, count 0;printf("plesae input a number: ");scanf("%d",&N);for(n1;n<N; n){ in…

在Delphi中如何创建和使用udl文件

如何在Delphi中创建和使用udl文件&#xff1a;方法一&#xff1a;直接弹出UDL对话框:use ADOConed; EditConnectionString(ADOQuery1);方法二&#xff1a;⑴、右键---新建---文本文档&#xff0c;重命名为 connSet.udl 。⑵、双击打开 connSet.udl 按提示操作配置数据库&#x…

redis事务的简单介绍

所谓事务应具有以下特效&#xff1a;原子性(Atomicity)&#xff0c; 一致性(Consistency)&#xff0c;隔离性(Isolation)&#xff0c;持久性(Durability)&#xff0c;简称ACID&#xff0c;但redis所提供的事务比较简单&#xff0c;它通过MULTI、EXEC、DISCARD和WATCH等命令实现…

Android Zip文件解压缩代码

在Android平台中如何实现Zip文件的解压缩功能呢? 因为Android内部已经集成了zlib库&#xff0c;对于英文和非密码的Zip文件解压缩还是比较简单的&#xff0c;下面Android123给大家一个解压缩zip的java代码&#xff0c;可以在Android上任何版本中使用&#xff0c;Unzip这个静态…

C语言指针(1)嵌入式linux

计算机中所有的数据都必须放在内存中&#xff0c;不同类型的数据占用的字节数不一样&#xff0c;例如 int占用4个字节&#xff0c;char 占用1个字节。为了正确地访问这些数据&#xff0c;必须为每个字节都编上号码&#xff0c;就像门牌号、身份证号一样&#xff0c;每个字节的编…

最全android Demo

1、BeautifulRefreshLayout-漂亮的美食下拉刷新https://github.com/android-cjj/BeautifulRefreshLayout/tree/BeautifulRefreshForFood2、Material Design-动画风格的选项卡tab切换功能https://github.com/neokree/MaterialTabs3、TwinklingRefreshLayout-支持下拉刷新和上拉加…

网站优化之Ajax优化及相关工具

web2.0大量的ajax的使用&#xff0c;提高了ui交互的效率&#xff0c;但是过度的滥用会带来不少的问题。 ajax使用注意事项&#xff1a; 1 尽量避免使用同步ajax调用。在一些登录的场合常常使用同步调用服务器的登录接口。 同步调用&#xff0c;需要将页面上的所有元素给锁定住&…

MessageQueue Message Looper Handler的解释说明

总结4个关键概念 1、MessageQueue&#xff1a;是一种数据结构&#xff0c;见名知义&#xff0c;就是一个消息队列&#xff0c;存放消息的地方。每一个线程最多只可以拥有一个MessageQueue数据结构。 创建一个线程的时候&#xff0c;并不会自动创建其MessageQueue。通常使用一个…

C语言中的内存分配

在任何程序设计环境及语言中&#xff0c;内存管理都十分重要。在目前的计算机系统或嵌入式系统中&#xff0c;内存资源仍然是有限的。因此在程序设计中&#xff0c;有效地管理内存资源是程序员首先考虑的问题。 第1节主要介绍内存管理基本概念&#xff0c;重点介绍C程序中内存的…

强化学习(十七) 基于模型的强化学习与Dyna算法框架

在前面我们讨论了基于价值的强化学习(Value Based RL)和基于策略的强化学习模型(Policy Based RL)&#xff0c;本篇我们讨论最后一种强化学习流派&#xff0c;基于模型的强化学习(Model Based RL)&#xff0c;以及基于模型的强化学习算法框架Dyna。 本篇主要参考了UCL强化学习课…