Spring Boot 之 RestTemplate

总结 Spring Boot 中 RestTemplate 的用法。

[TOC]

用法介绍

Spring Boot 中 RestTemplate 用法很简单。通过如下几行代码就可以很方便地调用 HTTP 服务。

1
2
3
4
5
6
7
8
public class RestTemplateDemo {
public static void main(String[] args) {
RestTemplate r = new RestTemplate();
Person person = r.getForObject(
"http://localhost:3000/api/temp/person.json", Person.class);
System.out.println(person);
}
}

HTTP 服务如下:

1
2
3
4
5
6
7
8
9
10
11
12
const express = require('express')
const app = express()

app.get('/', (req, res) => res.send('Hello World!'))

app.get('/api/temp/person.json', (req, res) => res.send(
{
'name': 'cm',
'age': 18
}
))
app.listen(3000, () => console.log('Example app listening on port 3000!'))

关于 RestTemplate 用法网上有不少参考文章,所以这里只列出几个要点,不对过多细节赘述。

  • HTTP 源 - RestTemplate 默认使用 HttpUrlConnection。可以通过 setRequestFactory() 切换到 Apache HttpComponentsNettyOkHttp
  • Converter - RestTemplate 默认使用 HttpMessageConverter 将 HTTP 消息转换成 POJO 或者从 POJO转换成HTTP消息。可以通过 setMessageConverters() 注册其他转换器

打印日志

调试过程中常常需要查看 RestTemplate 请求参数和响应参数。(最近参与开发一个电影票务系统,其中有个功能是使用 RestTemplate 调用第三方票务接口,我不小心将参数传错了导致接口调用失败。排查问题时没有想到先观察 RestTemplate 的 HTTP 请求和响应参数,浪费了不少时间)

使用 ClientHttpRequestInterceptor 可以非常方便地打印出请求参数与响应参数。

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
private static String formatHeaders(MultiValueMap<String, String> headers) {
return headers.entrySet().stream()
.map(entry -> {
List<String> values = entry.getValue();
return entry.getKey() + ":" + (values.size() == 1 ?
"\"" + values.get(0) + "\"" :
values.stream().map(s -> "\"" + s + "\"").collect(Collectors.joining(", ")));
})
.collect(Collectors.joining("\n", "-----\n", "\n-----"));
}

public static void main(String[] args) {
RestTemplate r = new RestTemplate();
r.setInterceptors(Collections.singletonList(
new ClientHttpRequestInterceptor() {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
System.out.println(request.getURI().toString());
System.out.println(formatHeaders(request.getHeaders()));
ClientHttpResponse rsp = execution.execute(request, body);
System.out.println(formatHeaders(rsp.getHeaders()));
return rsp;
}
}
));
}

请求参数和响应参数日志如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
http://localhost:3000/api/temp/person.json
-----
Accept:"text/plain, application/json, application/*+json, */*"
Content-Length:"0"
-----
-----
X-Powered-By:"Express"
Content-Type:"application/json; charset=utf-8"
Content-Length:"22"
ETag:"W/"16-ThD5gkGvRvX3v6wW+dfzNjgw6VA""
Date:"Wed, 28 Aug 2019 09:49:19 GMT"
Connection:"keep-alive"
-----

参考