- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Spring学习笔记之RestTemplate使用小结由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
作为一个java后端,需要通过http请求其他的网络资源可以说是一个比较常见的case了;一般怎么做呢?
可能大部分的小伙伴直接捞起apache的httpclient开始做,或者用其他的一些知名的开源库如okhttp, 当然原生的httpurlconnection也是没问题的 。
本篇博文则主要关注点放在sprig的生态下,利用resttemplate来发起http请求的使用姿势 。
i. resttempalate 基本使用 。
0. 目标 。
在介绍如何使用resttemplate之前,我们先抛出一些小目标,至少需要知道通过resttemplate可以做些什么,以及我们要用它来干些什么 。
简单的给出了一下常见的问题如下 。
上面的问题比较多,目测不是一篇博文可以弄完的,因此对这个拆解一下,本篇主要关注在resttemplate的简单get/post请求的使用方式上 。
1. 基本接口 。
捞出源码,看一下其给出的一些常用接口,基本上可以分为下面几种 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// get 请求
public
<t> t getforobject();
public
<t> responseentity<t> getforentity();
// head 请求
public
httpheaders headforheaders();
// post 请求
public
uri postforlocation();
public
<t> t postforobject();
public
<t> responseentity<t> postforentity();
// put 请求
public
void
put();
// pathch
public
<t> t patchforobject
// delete
public
void
delete()
// options
public
set<httpmethod> optionsforallow
// exchange
public
<t> responseentity<t> exchange()
|
上面提供的几个接口,基本上就是http提供的几种访问方式的对应,其中exchange却又不一样,后面细说 。
2. get请求 。
从上面的接口命名上,可以看出可以使用的有两种方式 getforobject 和 getforentity,那么这两种有什么区别?
a. 创建get接口 。
为了验证resttemplate的使用姿势,当然得先提供一个后端的rest服务,这了直接用了我个人的一个古诗词的后端接口,来作为简单的get测试使用 。
请求连接: https://story.hhui.top/detail?id=666106231640 。
返回结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
{
"status"
: {
"code"
:
200
,
"msg"
:
"success"
},
"result"
: {
"id"
:
666106231640
,
"title"
:
"西塞山二首(今谓之道士矶,即兴国军大冶县"
,
"author"
:
"王周"
,
"content"
:
"西塞名山立翠屏,浓岚横入半江青。\n千寻铁锁无由问,石壁空存道者形。\n匹妇顽然莫问因,匹夫何去望千春。\n翻思岵屺传诗什,举世曾无化石人。"
,
"explain"
:
""
,
"theme"
:
"无"
,
"dynasty"
:
"唐诗"
}
}
|
b. getforobject方式 。
首先看下完整的接口签名 。
1
2
3
4
5
6
7
8
|
@nullable
public
<t> t getforobject(string url,
class
<t> responsetype, object... urivariables)
throws
restclientexception ;
@nullable
public
<t> t getforobject(string url,
class
<t> responsetype, map<string, ?> urivariables)
throws
restclientexception ;
@nullable
public
<t> t getforobject(uri url,
class
<t> responsetype)
throws
restclientexception;
|
有三个重载的方法,从接口上也比较容易看出如何使用,其中有点疑惑的则是第一钟,参数应该怎么传了,下面给出上面几种的使用姿势 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
|
public
class
resttestmplatetest {
private
resttemplate resttemplate;
@before
public
void
init() {
resttemplate =
new
resttemplate();
}
@lombok
.data
static
class
innerres {
private
status status;
private
data result;
}
@lombok
.data
static
class
status {
int
code;
string msg;
}
@lombok
.data
static
class
data {
long
id;
string theme;
string title;
string dynasty;
string explain;
string content;
string author;
}
@test
public
void
testget() {
// 使用方法一,不带参数
string url =
"https://story.hhui.top/detail?id=666106231640"
;
innerres res = resttemplate.getforobject(url, innerres.
class
);
system.out.println(res);
// 使用方法一,传参替换
url =
"https://story.hhui.top/detail?id={?}"
;
res = resttemplate.getforobject(url, innerres.
class
,
"666106231640"
);
system.out.println(res);
// 使用方法二,map传参
url =
"https://story.hhui.top/detail?id={id}"
;
map<string, object> params =
new
hashmap<>();
params.put(
"id"
, 666106231640l);
res = resttemplate.getforobject(url, innerres.
class
, params);
system.out.println(res);
// 使用方法三,uri访问
uri uri = uri.create(
"https://story.hhui.top/detail?id=666106231640"
);
res = resttemplate.getforobject(uri, innerres.
class
);
system.out.println(res);
}
}
|
看上面的testcase,后面两个方法的使用没什么好说的,主要看一下org.springframework.web.client.resttemplate#getforobject(java.lang.string, java.lang.class<t>, java.lang.object...) 的使用姿势 。
上面执行后的截图如下 。
c. getforentity方式 。
既然getforobject有三种使用方法,那么getforentity理论上也应该有对应的三种方式 。
1
2
3
|
public
<t> responseentity<t> getforentity(string url,
class
<t> responsetype, object... urivariables)
throws
restclientexception ;
public
<t> responseentity<t> getforentity(string url,
class
<t> responsetype, map<string, ?> urivariables)
throws
restclientexception;
public
<t> responseentity<t> getforentity(uri url,
class
<t> responsetype)
throws
restclientexception;
|
因为使用姿势和上面一致,因此只拿一个进行测试 。
1
2
3
4
5
6
|
@test
public
void
testgetforentity() {
string url =
"https://story.hhui.top/detail?id=666106231640"
;
responseentity<innerres> res = resttemplate.getforentity(url, innerres.
class
);
system.out.println(res);
}
|
对这个,我们主要关注的就是responseentity封装中,多了哪些东西,截图如下 。
从上面可以看出,多了两个东西 。
3. post请求 。
从上面的接口说明上看,post请求除了有forobject 和 forentity之外,还多了个forlocation;其次post与get一个明显的区别就是传参的姿势问题,get的参数一般会待在url上;post的则更常见的是通过表单的方式提交 。
因此接下来关注的重点在于forlocation是什么,以及如何传参 。
a. post接口mock 。
首先创建一个简单的提供post请求的rest服务,基于spring-boot简单搭建一个,如下 。
1
2
3
4
5
6
7
8
9
10
|
@responsebody
@requestmapping
(path =
"post"
, method = {requestmethod.get, requestmethod.options, requestmethod.post})
public
string post(httpservletrequest request,
@requestparam
(value =
"email"
, required =
false
) string email,
@requestparam
(value =
"nick"
, required =
false
) string nick) {
map<string, object> map =
new
hashmap<>();
map.put(
"code"
,
"200"
);
map.put(
"result"
,
"add "
+ email +
" # "
+ nick +
" success!"
);
return
json.tojsonstring(map);
}
|
b. postforobject方法 。
首先看一下接口签名 。
1
2
3
4
5
|
public
<t> t postforobject(string url,
@nullable
object request,
class
<t> responsetype, object... urivariables)
throws
restclientexception ;
public
<t> t postforobject(string url,
@nullable
object request,
class
<t> responsetype, map<string, ?> urivariables)
throws
restclientexception;
public
<t> t postforobject(uri url,
@nullable
object request,
class
<t> responsetype)
throws
restclientexception ;
|
上面的三个方法,看起来和前面并没有太大的区别,只是多了一个request参数,那么具体的使用如何呢?
下面分别给出使用用例 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
@test
public
void
testpost() {
string url =
"http://localhost:8080/post"
;
string email =
"test@hhui.top"
;
string nick =
"一灰灰blog"
;
multivaluemap<string, string> request =
new
linkedmultivaluemap<>();
request.add(
"email"
, email);
request.add(
"nick"
, nick);
// 使用方法三
uri uri = uri.create(url);
string ans = resttemplate.postforobject(uri, request, string.
class
);
system.out.println(ans);
// 使用方法一
ans = resttemplate.postforobject(url, request, string.
class
);
system.out.println(ans);
// 使用方法一,但是结合表单参数和uri参数的方式,其中uri参数的填充和get请求一致
request.clear();
request.add(
"email"
, email);
ans = resttemplate.postforobject(url +
"?nick={?}"
, request, string.
class
, nick);
system.out.println(ans);
// 使用方法二
map<string, string> params =
new
hashmap<>();
params.put(
"nick"
, nick);
ans = resttemplate.postforobject(url +
"?nick={nick}"
, request, string.
class
, params);
system.out.println(ans);
}
|
复制代码上面分别给出了三种方法的调用方式,其中post传参区分为两种,一个是uri参数即拼接在url中的,还有一个就是表单参数 。
c. postforentity 。
和前面的使用姿势一样,无非是多了一层包装而已,略过不讲 。
d. postforlocation 。
这个与前面有点区别,从接口定义上来说,主要是 。
post 数据到一个url,返回新创建资源的url 。
同样提供了三个接口,分别如下,需要注意的是返回结果,为uri对象,即网络资源 。
1
2
3
4
5
6
7
|
public
uri postforlocation(string url,
@nullable
object request, object... urivariables)
throws
restclientexception ;
public
uri postforlocation(string url,
@nullable
object request, map<string, ?> urivariables)
throws
restclientexception ;
public
uri postforlocation(uri url,
@nullable
object request)
throws
restclientexception ;
|
那么什么样的接口适合用这种访问姿势呢?
想一下我们一般登录or注册都是post请求,而这些操作完成之后呢?大部分都是跳转到别的页面去了,这种场景下,就可以使用 postforlocation 了,提交数据,并获取返回的uri,一个测试如下 。
首先mock一个后端接口 。
1
2
3
4
5
6
7
8
9
10
11
|
@responsebody
@requestmapping
(path =
"success"
)
public
string loginsuccess(string email, string nick) {
return
"welcome "
+ nick;
}
@requestmapping
(path =
"post"
, method = {requestmethod.get, requestmethod.options, requestmethod.post})
public
string post(httpservletrequest request,
@requestparam
(value =
"email"
, required =
false
) string email,
@requestparam
(value =
"nick"
, required =
false
) string nick) {
return
"redirect:/success?email="
+ email +
"&nick="
+ nick +
"&status=success"
;
}
|
访问的测试用例,基本上和前面的一样,没有什么特别值得一说的 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@test
public
void
testpostlocation() {
string url =
"http://localhost:8080/post"
;
string email =
"test@hhui.top"
;
string nick =
"一灰灰blog"
;
multivaluemap<string, string> request =
new
linkedmultivaluemap<>();
request.add(
"email"
, email);
request.add(
"nick"
, nick);
// 使用方法三
uri uri = resttemplate.postforlocation(url, request);
system.out.println(uri);
}
|
执行结果如下 。
获取到的就是302跳转后端url,细心的朋友可能看到上面中文乱码的问题,如何解决呢?
一个简单的解决方案就是url编码一下 。
1
2
3
4
5
6
|
@requestmapping
(path =
"post"
, method = {requestmethod.get, requestmethod.options, requestmethod.post},
produces =
"charset/utf8"
)
public
string post(httpservletrequest request,
@requestparam
(value =
"email"
, required =
false
) string email,
@requestparam
(value =
"nick"
, required =
false
) string nick)
throws
unsupportedencodingexception {
return
"redirect:/success?email="
+ email +
"&nick="
+ urlencoder.encode(nick,
"utf-8"
) +
"&status=success"
;
}
|
ii. 小结 。
上面目前只给出了get/post两种请求方式的基本使用方式,并没有涉及到更高级的如添加请求头,添加证书,设置代理等,高级的使用篇等待下一篇出炉,下面小结一下上面的使用姿势 。
1. get请求 。
get请求中,参数一般都是带在url上,对于参数的填充,有两种方式,思路一致都是根据实际的参数来填充url中的占位符的内容;根据返回结果,也有两种方式,一个是只关心返回对象,另一个则包含了返回headers信心 参数填充 。
1、形如 http://story.hhui.top?id={0} 的 url 。
2、形如 http://story.hhui.top?id={id} 的 url 。
其实还有一种传参方式,就是path参数,填充方式和上面一样,并没有什么特殊的玩法,上面没有特别列出 。
返回结果 。
2. post请求 。
3. 其他 。
最前面提了多点关于网络请求的常见case,但是上面的介绍,明显只处于基础篇,我们还需要关注的有 。
上面可能还停留在应用篇,对于源码和实现有兴趣的话,问题也就来了 。
小小的一个工具类,其实东西还挺多的,接下来的小目标,就是针对上面提出的点,逐一进行研究 。
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我的支持.
原文链接:https://juejin.im/post/5b717eab6fb9a0096e21cc24 。
最后此篇关于Spring学习笔记之RestTemplate使用小结的文章就讲到这里了,如果你想了解更多关于Spring学习笔记之RestTemplate使用小结的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我编写了以下代码来测试同步 RestTemplate 和 AsyncRestTemplate 的性能。我只是在 POSTMAN 上手动运行了几次。 我们只是将 10 个引用传递给 GET 调用,以便我
这种方式创建RestTemplate有什么区别 RestTemplate restTemplate = restTemplateBuilder .setConnectT
这个问题已经有答案了: IllegalArgumentException: Not enough variable values available with RestTemplate? (2 个回答
这是我的应用程序的主类 @SpringBootApplication (scanBasePackages = { "com.xyz.*" }) @EnableAsync @EnableAspectJA
我当前的代码: RestTemplate restTemplate = new RestTemplate(); restTemplate.getMessageConverters().add(new
我将开发一个简单的 Spring MVC Web 应用程序,它将使用 Heroku 上的远程 RESTful 服务。 我希望 MVC Web 应用程序根据 Controller 调用 REST 服务。
项目场景: Spring 的 RestTemplate 是一个健壮的、流行的基于 Java 的 Http客户端。 RestTemplate实现request param参数传送,如果如下所示,直接传一
我想通过 RestTemplate 发送请求。但是我的网址有大括号('{','}'),因此我有异常(exception):“没有足够的变量值可用于扩展......”。 我尝试通过 uri UriCom
有一个 RestFull 方法返回一个菜单对象列表 public ResponseEntity> getMenus() { .. } 但我不知道如何从 RestTemplate 中获取它们,从 Res
摘要: RestTemplate与REST资源交互的方法涵盖了HTTP请求方法,包括get, post, put, delete。 本文分享自华为云社区《Springboot RestTemplate
我有一个 springboot 休息服务 A 使用 restTemplate 调用休息服务 B。休息服务 A 的 restTemplate bean 创建如下,超时设置如下面的代码片段所示。 @Bea
我有一个 @Service有几种方法,每种方法使用不同的 web api。每个调用都应该有一个自定义的读取超时。 拥有一个 RestTemplate 实例并在每个方法中通过工厂更改超时是否是线程安全的
这是我的休息模板配置, @Bean @Qualifier("myRestService") public RestTemplate createRestTemplate(@Va
是否可以使用 RestTemplateBuilder 创建仅带有不记名 header 和 token 的 RestTemplate 实例? 我知道我可以使用 RestTemplate 交换并在 Htt
我正在尝试对请求正文执行 DELETE,但我不断收到 400(错误请求)错误。当我在 swagger/postman 中这样做时,它成功地删除了记录。但是从 Java 代码我不能这样做 外部 API
我需要创建 RestTemplate 请求,它将发送图像以通过 PHP 应用程序上传。 我的代码是: Resource resource = new FileSystemResource("/User
我正在使用 swagger codegen ( on this Zoura swagger ) 创建 Java/rest 模板客户端。我正在使用 swagger Gradle 插件: id "org.
我有Restful API,当找不到某个项目时会响应404错误,但是根据未找到该项目的原因(未知,不可用等),会有不同的消息,可以使用Spring MVC通过以下方式完成: response.send
我正在使用 Spring 中的 RestTemplate 来查询搜索服务。我在进行正确的序列化方面遇到了一些困难。如果我使用此方法,restTemplate 将返回一个列表。我不明白如何传递参数化类型
我们有这样的代码,它使用 OData 来指定资源(为简单起见,在此处使用公司代码进行硬编码): String uri = "[my_endpoint]/companyprofiles.read?$fi
我是一名优秀的程序员,十分优秀!