关于rest可参考第3篇,而RestTemplate就是由spring提供的,用于在后台进行rest请求的,比繁琐的HttpClient要方便很多。
pom.xml
从本篇开始,后续文章都使用spring boot2,要求jdk版本至少8。之前的文章仍然适用于低版本的jdk,继续保留。spring boot 1和2大部分用法是一样的,只是有些功能做了细节调整。如默认连接池从tomcat变成了HikariCP,actuator有较大改动等。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
rest服务端
先创建一个服务端项目,项目中有一个接口方法提供服务,如下。端口为8081,启动项目
@RestController
public class HelloController {
@RequestMapping("/server")
public String server() {
return "hello";
}
}
rest客户端
创建客户端项目,在配置类中,使用RestTemplateBuilder来构建一个RestTemplate。
@Autowired
RestTemplateBuilder restTemplateBuilder;
//在配置类中使用restTemplateBuilder构建RestTemplate实例
@Bean
public RestTemplate restTemplate(){
return restTemplateBuilder.build();
}
在控制层使用restTemplate来访问服务端,客户端端口为8080,启动项目
@RestController
public class ClientController {
@Autowired
RestTemplate restTemplate;
@RequestMapping("/client")
public String client() {
//通过restTemplate请求rest服务端
String result = restTemplate.getForObject("http://localhost:8081/server", String.class);
return result;
}
getForObject方法
getForObject指get请求,并返回一个Object对象。这里有2个方法参数
- 第1个参数:请求的url地址
- 第2个参数:返回的结果类型,这里String.class表示返回结果是一个字符串。
运行结果
如图,通过浏览器请求http://localhost:8080/client,客户端又通过restTemplate请求了服务端的数据hello,最终返回。
请求参数
- 可以使用map来封装请求参数,并作为getForObject的第三个参数,同时修改url如下,map中的"1"会替换url中的{1},"2"会替换url中的{2}
Map map = new HashMap();
map.put("1", "hello");
map.put("2", "world");
String result = restTemplate.getForObject("http://localhost:8081/server?param1={1}¶m2={2}", String.class,map);
- 也可以直接将要传递的值放到getForObject方法的参数结尾,数量不限,它会按顺序替换{1}和{2}
String result = restTemplate.getForObject("http://localhost:8081/server?param1={1}¶m2={2}", String.class, "hello", "world");
getForEntity方法
getForEntity和getForObject的用法是一样的,只是其返回结果是一个ResponseEntity,其中包含了更多的响应信息,比如:
ResponseEntity response = restTemplate.getForEntity("http://localhost:8081/server",String.class);
response.getHeaders(); //响应头
response.getStatusCode(); //响应码
response.getBody(); //响应体,即前面的result
postForObject方法
postForObject指post请求,并返回一个Object对象。
String response = restTemplate.postForObject("http://localhost:8081/server?param1={1}¶m2={2}", null, String.class, "hello", "world");
- postForObject第1个参数就是getForObject第1个参数。
- postForObject第3个参数就是getForObject第2个参数。
- postForObject第4个及以后的参数就是getForObject第3个及以后的参数。
postForObject除了第2个参数为null,其它地方用法和getForObject是一模一样的。但是post请求传参通常不是写在url上实现的,而是放在请求体中。此时,就需要使用第2个参数来传参,同时可省略第4个参数的url传参,如下
Map map = new HashMap();
map.put("param1", "hello");
map.put("param2", "world");
String response = restTemplate.postForObject("http://localhost:8081/server", map, String.class);
注意,服务端端接收不同参数时,语法也有所不同,如下
public String server(@RequestBody Map map,String param1,String param2)
- @RequestBody Map map:此注解可用于接收请求体,即postForObject的第2个map参数。此注解第3篇有讲过。
- String param1,String param2:用于接收postForObject第4个及以后参数的url传参 。
HttpEntity
postForObject的第2个参数其实是HttpEntity,这个类主要有三种构造方法,如下
- new HttpEntity(请求体)
- new HttpEntity(请求头)
- new HttpEntity(请求体,请求头)
当我前面传了一个map参数时,系统内部会自动使用第一种方法,将这个map作为
请求体,并
封装成
HttpEntity。以下以第三种方法为例,介绍如何使用HttpEntity同时发送请求体和请求头:
//请求体
Map map = new HashMap();
map.put("param1", "hello");
map.put("param2", "world");
//请求头
MultiValueMap headers = new HttpHeaders();
headers.add("Accept", "text/xml");
//请求内容封装成httpEntity
HttpEntity httpEntity= new HttpEntity(map,headers);
restTemplate.postForObject("http://localhost:8081/server", httpEntity, String.class);
postForEntity
和getForEntity原理是一样的
配置超时
如果要设置请求的超时时间,可修改前面restTemplate的构建代码,如下
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = restTemplateBuilder
.setConnectTimeout(1000) //连接超时为1秒
.setReadTimeout(1000) //请求超时为1秒
.build();
return restTemplate;
}