restTemplate 使用
参考https://www.jianshu.com/p/27a82c494413,侵权删(仅学习后敲一遍)
restTemplate
简述RestTemplate
是Spring用于同步client端的核心类,简化了与http服务的通信,并满足RestFul原则,程序代码可以给它提供URL,并提取结果。默认情况下,RestTemplate默认依赖jdk的HTTP连接工具。当然你也可以 通过setRequestFactory属性切换到不同的HTTP源,比如Apache HttpComponents、Netty和OkHttp。
RestTemplate能大幅简化了提交表单数据的难度,并且附带了自动转换JSON数据的功能,但只有理解了HttpEntity的组成结构(header与body),且理解了与uriVariables之间的差异,才能真正掌握其用法。这一点在Post请求更加突出,下面会介绍到。
GET 请求实践
getForObject()方法
getForObject()其实比getForEntity()多包含了将HTTP转成POJO的功能,但是getForObject没有处理response的能力。因为它拿到手的就是成型的pojo。省略了很多response的信息。
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables){}
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
public <T> T getForObject(URI url, Class<T> responseType)
带参数get请求
/**
* get 请求 ,参数(占位符)传参
*/
@Test
public void testGet(){
String api = "http://192.168.6.9:8060/ronghe/sendMessage/register?username={username}";
User user = this.restTemplate.getForObject(api, User.class ,"13588888888");
System.out.println(user);
}
/**
* get 请求 ,用 map 传参
*/
@Test
public void testGet2(){
String api = "http://192.168.6.9:8060/ronghe/sendMessage/register?username={username}";
Map<String,String> map = new HashMap<>();
map.put("username","13588888888");
User user = this.restTemplate.getForObject(api, User.class ,map);
System.out.println(user);
}
getForEntity()方法
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables){}
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables){}
public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType){}
带参数的get请求
/**
* getForEntity()方法 , 有返回值
*/
@Test
public void testGEtForEntity(){
String api = "http://192.168.6.9:8060/ronghe/exBox/countFreeBox?cabinetNo={cabinetNo}&boxClassify={boxClassify}";
Map<String,String> map = new HashMap<>();
map.put("cabinetNo","99999999");
map.put("boxClassify","2");
ResponseEntity<BoxTypeDTO> responseEntity = restTemplate.getForEntity(api,BoxTypeDTO.class,map );
BoxTypeDTO boxTypeDTO = responseEntity.getBody();
}
POST 请求实践
也分为 postForEntity
和 getForObject
方法
postForEntity 方法
postForObject 方法形参一致
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException{}
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {}
public <T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException {}
返回的是ResponseEntity对象,如果需要转换成pojo,还需要json工具类的引入,这个按个人喜好用。不会解析json的可以百度FastJson或者Jackson等工具类。然后我们就研究一下ResponseEntity下面有啥方法。
ResponseEntity、HttpStatus、BodyBuilder结构
ResponseEntity.java
public HttpStatus getStatusCode(){}
public int getStatusCodeValue(){}
public boolean equals(@Nullable Object other) {}
public String toString() {}
public static BodyBuilder status(HttpStatus status) {}
public static BodyBuilder ok() {}
public static <T> ResponseEntity<T> ok(T body) {}
public static BodyBuilder created(URI location) {}
...
HttpStatus.java
public enum HttpStatus {
public boolean is1xxInformational() {}
public boolean is2xxSuccessful() {}
public boolean is3xxRedirection() {}
public boolean is4xxClientError() {}
public boolean is5xxServerError() {}
public boolean isError() {}
}
BodyBuilder.java
public interface BodyBuilder extends HeadersBuilder<BodyBuilder> {
//设置正文的长度,以字节为单位,由Content-Length标头
BodyBuilder contentLength(long contentLength);
//设置body的MediaType 类型
BodyBuilder contentType(MediaType contentType);
//设置响应实体的主体并返回它。
<T> ResponseEntity<T> body(@Nullable T body);
}
可以看出来,ResponseEntity包含了HttpStatus和BodyBuilder的这些信息,这更方便我们处理response原生的东西。
post 方法带参数
@Test
public void test4(){
String api = "http://192.168.6.9:8060/ronghe/exBox/countFreeBox";
BoxCountDTO boxCountDTO = new BoxCountDTO();
boxCountDTO.setBoxClassify("2");
boxCountDTO.setCabinetNo("99999999");
ResponseEntity<BoxTypeDTO> responseEntity = restTemplate.postForEntity(api , boxCountDTO, BoxTypeDTO.class);
BoxTypeDTO body = responseEntity.getBody();
}
get 方法带参数带请求头
我习惯用String.class
去接收返回值,然后通过Json 转换,获取对象。
个人不建议和别人对接接口的时候,直接用对象的形式去返回(因为之前项目的接口被人改了,也不知道自己去改)
@Test
public void test4(){
String api = "http://192.168.6.9:8060/ronghe/exBox/countFreeBox";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 注意,自己测试的时候,需要把@RequestBody 注解去掉
MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
map.add("cabinetNo", "99999999");
map.add("boxClassify","3");
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity( api, request , String.class );
String body = response.getBody();
也可以全局设置请求头,但是好似一个完美的解决方案,实质太局限性的操作了,我还是喜欢每个请求里写上,防止耦合…
未完待续。。。