概览
上一篇介绍了如何使用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服务提供的接口服务
简单入门
实例代码对应的仓库地址:
引入依赖
在pom.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服务,添加如下配置内容:
# 用来修改web服务的端口
server:
port: 8081
编写代码
自定义RestTemplate
@Bean
public RestTemplate customRestTemplate(){
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectionRequestTimeout(3000);
httpRequestFactory.setConnectTimeout(3000);
httpRequestFactory.setReadTimeout(3000);
return new RestTemplate(httpRequestFactory);
}
定义统一响应VO R
@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
@Data
public class UserReqVO implements Serializable {
private String username;
private String password;
}
定义User响应VO
@Data
public class UserRespVO implements Serializable {
private Integer id;
private String username;
private Date createTime;
}
编写UserClient使用restTemplate访问接口
@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消息头等信息。
单元测试
@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中间件等技术。