前言
Spring Boot整合RestTemplate实现接口调用入门。
什么是RestTemplate
RestTemplate
是Spring框架中提供的用于以同步方式发送HTTP请求和处理HTTP响应的类。它是一个用于访问RESTful服务的模板类,简化了在Java应用程序中进行HTTP通信的过程。
RestTemplate
提供了一系列方法来执行HTTP请求,例如GET、POST、PUT、DELETE等,并能够自动将HTTP响应转换为Java对象(如JSON转换为POJO)。它支持各种HTTP协议,如HTTP、HTTPS,并且可以与其他Spring框架组件(如Spring MVC和Spring Boot)无缝集成。
底层实现上,RestTemplate
默认构造函数使用java.net.HttpURLConnection
执行请求。用户可以通过实现ClientHttpRequestFactory
接口来切换到不同的HTTP库。内置支持以下库:
- Apache HttpComponents
- Netty
- OkHttp
RestTemplate提供的方法
RestTemplate 提供高度封装的接口。
方法名 | 描述 |
---|---|
getForObject | 通过GET请求获取资源的表示。 |
getForEntity | 通过GET请求获取资源的ResponseEntity (包含状态、响应头和响应体)。 |
headForHeaders | 通过HEAD请求获取资源的所有头信息。 |
postForLocation | 通过POST请求创建新资源,并从响应中返回Location头信息。 |
postForObject | 通过POST请求创建新资源,并从响应中返回资源的表示。 |
postForEntity | 通过POST请求创建新资源,并从响应中返回资源的ResponseEntity (包含状态、响应头和响应体)。 |
put | 通过PUT请求创建或更新资源。 |
patchForObject | 通过PATCH请求更新资源,并从响应中返回资源的表示。请注意,JDK HttpURLConnection不支持PATCH,但Apache HttpComponents和其他库支持。 |
delete | 通过DELETE请求删除指定URI的资源。 |
optionsForAllow | 通过OPTIONS请求获取资源允许的HTTP方法。 |
exchange | 通用的(灵活但不局限于特定用途)请求方法,提供额外的灵活性。它接受RequestEntity 作为输入,其中包含HTTP方法、URL、头信息和请求体,并返回ResponseEntity 。 |
execute | 最通用的执行请求的方式,完全控制请求准备和响应提取,通过回调接口实现。 |
Springboot整合RestTemplate
分别采用默认方式和Apache HttpComponents进行实践。
默认方式
仅需要:1
2
3
4
5<!-- author: SilenceZheng66 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
添加配置类:1
2
3
4
5
6
7
8// author: SilenceZheng66
public class RestTemplateConfig {
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
在控制器中加入restTemplate
:1
2
3
4// author: SilenceZheng66
private RestTemplate restTemplate;
当然也可以在Service中加入:1
2
3
4
5
6
7// author: SilenceZheng66
private final RestTemplate restTemplate;
public ServiceImpl(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
编写简单的接口访问代码:1
2
3
4
5
6
7
8
9
10
11
12// author: SilenceZheng66
public void makeHttpGetRequest() {
String url = "https://api.example.com/data";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
if (response.getStatusCode().is2xxSuccessful()) {
String responseBody = response.getBody();
// 处理响应数据
} else {
// 处理错误响应
}
}
Apache HttpComponents发送请求
Apache HttpComponents是一个开源的Java HTTP库,用于处理HTTP请求和响应。它是Apache软件基金会下的一个项目,提供了一组可重用的组件,可以轻松地在Java应用程序中进行HTTP通信。
Apache HttpComponents由两个子项目组成:
HttpClient:这是一个完整的HTTP客户端库,用于发送HTTP请求和处理HTTP响应。它提供了一组简单而强大的API,可以执行各种HTTP方法(GET、POST、PUT、DELETE等),设置请求头,处理响应,处理Cookies等。
HttpCore:这是一个核心HTTP处理库,为HTTP客户端和服务器提供了低级别的HTTP支持。它定义了HTTP协议的基本元素,如请求、响应、头部、实体等,为客户端和服务器实现提供了基础功能。
添加HttpClient依赖:1
2
3
4
5
6<!-- author: SilenceZheng66 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
在配置文件中写入参数:1
2
3
4
5
6
7http_pool:
max_total: 200
default_max_per_route: 100
connect_timeout: 5000
connection_request_timeout: 1000
socket_timeout: 65000
validate_after_inactivity: 2000
创建HTTP参数类:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// author: SilenceZheng66
public class HttpValues {
private int maxTotal;
private int maxPerRoute;
private int connTimeOut;
private int connReqTimeOut;
private int socketTimeout;
private int inactivity;
}
创建配置类: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
58
59
60
61
62
63
64
65
66
67
68// author: SilenceZheng66
public class RestTemplateConfig {
private HttpValues appValues;
public RestTemplate restTemplate() {
return new RestTemplate(httpRequestFactory());
}
/**
* 创建一个自定义的 ClientHttpRequestFactory Bean。
* ClientHttpRequestFactory 是 Spring 提供的用于创建 ClientHttpRequest 的工厂接口。
* 这里使用了基于 Apache HttpComponents 的 HttpComponentsClientHttpRequestFactory 实现。
* HttpComponentsClientHttpRequestFactory 使用了自定义的 HttpClient 对象来发送 HTTP 请求。
*
* @return 返回一个 ClientHttpRequestFactory 对象,用于创建 ClientHttpRequest。
*/
public ClientHttpRequestFactory httpRequestFactory() {
// 创建一个新的 HttpComponentsClientHttpRequestFactory 对象,并传入自定义的 HttpClient。
return new HttpComponentsClientHttpRequestFactory(httpClient());
}
/**
* 创建一个自定义的 HttpClient Bean。
* 这个方法使用了连接池来管理 HTTP 连接,提高了性能和效率。
*
* @return 返回一个 HttpClient 对象,可以用于发送 HTTP 请求。
*/
public HttpClient httpClient() {
// 创建一个 Registry,用于管理不同协议的连接工厂。
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
// 注册 HTTP 协议的连接工厂,使用默认的 PlainConnectionSocketFactory。
.register("http", PlainConnectionSocketFactory.getSocketFactory())
// 注册 HTTPS 协议的连接工厂,使用默认的 SSLConnectionSocketFactory。
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
// 创建一个连接池管理器,用于管理连接的复用和回收。
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
// 设置连接池的最大连接数。
connectionManager.setMaxTotal(appValues.getMaxTotal());
// 设置每个路由的最大连接数。
connectionManager.setDefaultMaxPerRoute(appValues.getMaxPerRoute());
// 设置连接空闲多长时间后进行验证,避免空闲连接过多占用资源。
connectionManager.setValidateAfterInactivity(appValues.getInactivity());
// 创建一个请求配置对象,用于设置连接超时和读写超时等参数。
RequestConfig requestConfig = RequestConfig.custom()
// 服务器返回数据的时间,超过该时间将抛出 read timeout 异常。
.setSocketTimeout(appValues.getSocketTimeout())
// 连接上服务器的时间,超过该时间将抛出 connect timeout 异常。
.setConnectTimeout(appValues.getConnTimeOut())
// 从连接池中获取连接的超时时间,超过该时间将抛出 ConnectionPoolTimeoutException 异常。
.setConnectionRequestTimeout(appValues.getConnReqTimeOut())
.build();
// 使用 HttpClientBuilder 创建一个 HttpClient 对象,并设置连接池管理器和请求配置。
return HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(connectionManager)
.build();
}
}
使用示例: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// author: SilenceZheng66
public ResponseEntity<Students> getStudentById( Long id){
Students student = studentsService.getById(id);
if (student != null) {
// 如果找到学生,返回状态码200 OK和学生对象
return ResponseEntity.ok(student);
} else {
// 如果未找到学生,返回状态码404 NOT FOUND
return ResponseEntity.notFound().build();
}
}
public ResponseEntity<String> restGetTest( Long id){
String url = "http://localhost:48081/students/" + String.valueOf(id+1);
// 这里应该加入异常处理
ResponseEntity<Students> response = restTemplate.getForEntity(url, Students.class);
// 获取响应
if (response.getStatusCode().is2xxSuccessful()) {
Students responseBody = response.getBody();
if (responseBody!=null) return ResponseEntity.ok(responseBody.toString());
else return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Not Found");
// 处理响应数据
} else {
// 处理错误响应
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Bad Request");
}
}
对于带路径参数的URL,可以用这种方式:1
2
3// author: SilenceZheng66
String url = "http://localhost:48081/students/{1}";
ResponseEntity<Students> response = restTemplate.getForEntity(url, Students.class, id+1);
对于添加请求头、Cookie、文件上传等等更多用法,在使用时查阅、积累即可。
参考
[1] https://docs.spring.io/spring-framework/docs/5.1.9.RELEASE/spring-framework-reference/integration.html#rest-resttemplate
[2] https://zhuanlan.zhihu.com/p/258121569
[3] https://www.cnblogs.com/javazhiyin/p/9851775.html
后记
首发于 silencezheng.top,转载请注明出处。