SpringBoot 2x系列:RestTemplate

概览

上一篇介绍了如何使用Spring Boot构建RESTful风格Web服务的实现方法,juejin.cn/post/695494…,完成了Web服务构建后,大部分情况下将接口提供给前端的小伙伴去调用就可以了,实际开发过程中也会涉及到后端去调用另外一个后端写的接口,我们需要做的事情就是如何对服务进行消费,目前常用有三种方式

  • JDK自带的HttpConnection
  • Apache的HttpClient
  • Spring封装的RestTemplate

严格意思是RestTemplate底层并没有自己去实现Http协议栈,RestTemplate只是Spring定义一个模板,类似JDBCTemplate,底层实际发送Http请求还是通过HttpConnetion或者HttpClient,具体使用哪个类库,可以在自定义RestTemplate的时候来指定。当然相较传统的 HttpClient 客户端工具类库,RestTemplate 在编码的简便性以及异常的处理等方面都做了很多改进。

RestTemplate常用方法介绍

在远程访问上,RestTemplate内置了一批常用的工具方法,我们可以根据HTTP的语义以及RESTful的设计原则对这些方法进行归类:

HTTP方法 RestTemplate方法组
GET getForObject/getForEntity
POST postForLocation/postForObject/postForEntity
PUT put
DELETE delete
Header headForHeaders
不限 Exchange/execute

好,常用方法介绍完后,接下来我们通过一个简单的入门,把这些方法实际走一边,注意:本节的入门Demo需要依赖上一节介绍构建RESTful Web服务提供的接口服务

简单入门

实例代码对应的仓库地址:

github.com/dragon8844/…

gitee.com/drag0n/spri…

引入依赖

在pom.xml的文件中引入相关依赖:

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
xml复制代码<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!--简化代码-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!--使用httpclient实现http客户端-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>

<!-- 方便等会写单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>

添加配置

在resources目录下创建应用的配置文件application.yml,我们这里使用8081,8080端口留给RESTful web服务,添加如下配置内容:

1
2
3
yaml复制代码# 用来修改web服务的端口
server:
port: 8081

编写代码

自定义RestTemplate

1
2
3
4
5
6
7
8
9
java复制代码@Bean
public RestTemplate customRestTemplate(){
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(3000);
        httpRequestFactory.setConnectTimeout(3000);
        httpRequestFactory.setReadTimeout(3000);
 
        return new RestTemplate(httpRequestFactory);
}

定义统一响应VO R

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
java复制代码@Data
public class R<T> implements Serializable {
private static final String DEFAULT_SUCCESS_MSG = "请求成功";
private static final int DEFAULT_SUCCESS_CODE = 0;
public static final int SUCCESS = DEFAULT_SUCCESS_CODE;
private Integer code;
private String msg;
private T data;
public static<T> R ok(T data){
R jsonResult = new R();
jsonResult.setCode(DEFAULT_SUCCESS_CODE);
jsonResult.setMsg(DEFAULT_SUCCESS_MSG);
jsonResult.setData(data);
return jsonResult;
}
public static<T> R err(int code, String msg , T data){
R jsonResult = new R();
jsonResult.setCode(code);
jsonResult.setMsg(msg);
jsonResult.setData(data);
return jsonResult;
}
public static<T> R err(int code, String msg){
R jsonResult = new R();
jsonResult.setCode(code);
jsonResult.setMsg(msg);
return jsonResult;
}
}

定义User请求VO

1
2
3
4
5
6
7
java复制代码@Data
public class UserReqVO implements Serializable {

private String username;
private String password;

}

定义User响应VO

1
2
3
4
5
6
7
java复制代码@Data
public class UserRespVO implements Serializable {

private Integer id;
private String username;
private Date createTime;
}

编写UserClient使用restTemplate访问接口

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
java复制代码@Component
@Slf4j
public class UserClient {

@Resource
RestTemplate restTemplate;

public R<UserRespVO> getForObject(Integer id){
Map<String, Object> uriVariables = new HashMap<>(1);
uriVariables.put("id", id);
R r = restTemplate.getForObject("http://localhost:8080/v1/user/{id}", R.class, uriVariables);
return r;
}

public R<UserRespVO> getForEntity(Integer id){
Map<String, Object> uriVariables = new HashMap<>(1);
uriVariables.put("id", id);
ResponseEntity<R> r = restTemplate.getForEntity("http://localhost:8080/v1/user/{id}", R.class,uriVariables);
log.info(r.getHeaders().toString());
return r.getBody();
}

public R<Boolean> postForObject(UserReqVO userReqVO){
R r = restTemplate.postForObject("http://localhost:8080/v1/user", userReqVO, R.class);
return r;
}

public R<Boolean> postForEntity(UserReqVO userReqVO){
ResponseEntity<R> r = restTemplate.postForEntity("http://localhost:8080/v1/user", userReqVO, R.class);
log.info(r.getHeaders().toString());
return r.getBody();
}

/**
* exchange 是一个通用且统一的方法,它既能发送 GET 和 POST 请求,也能用于发送其他各种类型的请求。
* @return
*/
public R<UserRespVO> exchange(Integer id){
Map<String, Object> uriVariables = new HashMap<>(1);
uriVariables.put("id", id);
ResponseEntity<R> r = restTemplate.exchange("http://localhost:8080/v1/user/{id}", HttpMethod.GET, null, R.class, uriVariables);
log.info(r.getHeaders().toString());
return r.getBody();
}

public R<Boolean> put(Integer id, UserReqVO userReqVO){
restTemplate.put("http://localhost:8080/v1/user/{id}", userReqVO, id);
return R.ok(true);
}

public R<Boolean> delete(Integer id){
restTemplate.delete("http://localhost:8080/v1/user/{id}", id);
return R.ok(true);
}
}
  • getForObject() 发送一个HTTP GET请求,返回的请求体将映射为业务对象
  • getForEntity() 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的业务对象,在这个对象中还包含了 HTTP 消息头等信息,而且getForObject方法返回的只是业务对象
  • postForObject() POST 数据到一个URL,返回根据响应体匹配形成的对象
  • postForEntity()
    POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得
    到的,和getForEntity类似,ResponseEntity对象中还包含了HTTP消息头等信息。
  • put() PUT 资源到特定的URL
  • delete() 在特定的URL上对资源执行HTTP DELETE操作
  • exchange()
    在URL上执行特定的HTTP方法,是一个通用且统一的方法,它既能发送 GET 和 POST 请求,也能用于发送其他各种类型的请求。返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的,同时包含了HTTP消息头等信息。

单元测试

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
java复制代码@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class UserClientTest {

@Resource
UserClient userClient;

@Test
public void getForObject() {

R r = userClient.getForObject(9991);
log.info("result : {}", r);
}
@Test
public void getForEntity() {
R r = userClient.getForEntity(9991);
log.info("result : {}", r);
}
@Test
public void postForObject() {
UserReqVO userReqVO = new UserReqVO();
userReqVO.setUsername("张三");
userReqVO.setPassword("123456");
R r = userClient.postForObject(userReqVO);
log.info("result : {}", r);
}
@Test
public void postForEntity() {
UserReqVO userReqVO = new UserReqVO();
userReqVO.setUsername("张三");
userReqVO.setPassword("123456");
R r = userClient.postForEntity(userReqVO);
log.info("result : {}", r);
}
@Test
public void exchange() {
R r = userClient.exchange(9991);
log.info("result : {}", r);
}
@Test
public void put() {
UserReqVO userReqVO = new UserReqVO();
userReqVO.setUsername("张三");
userReqVO.setPassword("123456");
R r = userClient.put(1,userReqVO);
log.info("result : {}", r);
}
@Test
public void delete() {
R r = userClient.delete(1);
log.info("result : {}",r);
}
}

小结

我们在Spring Boot构建RESTful风格Web服务的基础,通过引入RestTemplate模板实现了对远程服务接口的访问,RestTemplate 为开发人员提供了一大批有用的工具方法来实现 HTTP 请求的发送以及响应的获取。同时,该模板类还开发了一些定制化的入口供开发人员嵌入,用来实现对 HTTP 请求过程进行精细化管理的处理逻辑。和 JdbcTemplate 一样,RestTemplate 在设计和实现上也是一款非常有效的工具类。希望这个简单的入门对您有帮忙~

最后说一句

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下,您的支持是我坚持写作最大的动力,多谢支持。

此外,关注公众号:黑色的灯塔,专注Java后端技术分享,涵盖Spring,Spring Boot,SpringCloud,Docker,Kubernetes中间件等技术。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%