RestTemplate 简介
RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。RestTemplate 继承自 InterceptingHttpAccessor 并且实现了 RestOperations 接口,其中 RestOperations 接口定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现。接下来我们就来看看这些操作方法的使用。
RestTemplate实战使用
写一个工具类RestUtil,在实际项目中往往使用单例模式来设计RestTemplate
/**
* RestAPI 调用器
*/
private final static RestTemplate RT;
static {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
// 设置连接超时时间,单位为毫秒
requestFactory.setConnectTimeout(30000);
// 设置读取超时时间,单位为毫秒
requestFactory.setReadTimeout(30000);
RT = new RestTemplate(requestFactory);
// 解决乱码问题
RT.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
}
public static RestTemplate getRestTemplate() {
return RT;
}
在其他地方需要使用时只需一列下行代码即可:
private static RestTemplate restTemplate = RestUtil.getRestTemplate();
POST请求
POST请求中有三个方法,分别是postForEntity,postForObject,postForLocation。这三类方法最直观的就是返回值类型定义不同,具体如下代码所示:
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
ResponseExtractor<ResponseEntity<T>> responseExtractor = this.responseEntityExtractor(responseType);
return (ResponseEntity)nonNull(this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables));
}
@Nullable
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Object[])uriVariables);
}
@Nullable
// 返回值为URI对象,因为Post请求最常用来添加数据,如果需要将刚刚添加成功的数据的URL返回来,此时就可以使用这个方法
public URI postForLocation(String url, @Nullable Object request, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request);
HttpHeaders headers = (HttpHeaders)this.execute(url, HttpMethod.POST, requestCallback, this.headersExtractor(), uriVariables);
return headers != null ? headers.getLocation() : null;
}
参数类型分别为:
1)String url 请求的url路径
2)@Nullable Object request 可为空的请求对象
3)Class<T> responseType 返回类型的类定义
4)Object... uriVariables 动态的uri参数,可传递多个
5)Map<String, ?> uriVariables 以Map方式存储的uri参数
1、postForEntity方法
参数可以是key/value类型也可以是json串
(一)传递key/value参数
首先在服务端写一个Post请求的接口
@PostMapping(value = "/synchronizationCar")
public String synchronizationCar(@RequestBody MultiValueMap map) {
System.out.println(map.get("name"));
System.out.println(map.get("sex"));
System.out.println(map.get("description"));
return "";
}
客户端请求代码如下:
public static void main(String[] args) {
HttpHeaders headers = new HttpHeaders();
MultiValueMap map = new LinkedMultiValueMap();
map.add("name", "雷锋");
map.add("sex", "男");
map.add("description", "乐于助人的好人");
HttpEntity entity = new HttpEntity<>(map, headers);
ResponseEntity<String> json = restTemplate.postForEntity("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", entity, String.class);
}
(二)传递json字符串
首先服务端解析代码如下:
@PostMapping(value = "/synchronizationCar")
public String synchronizationCar(@RequestBody String s) {
JSONObject jsonObject = JSONObject.parseObject(s);
JSONArray jsonArray = jsonObject.getJSONArray("data");
List<BisBasicsCar> list = jsonArray.toJavaList(BisBasicsCar.class);
System.out.println(list.size());
return "ok";
}
客户端请求代码如下:
private void basicsSynchronization(){
//车辆表
List<BisBasicsCar> list = bisBasicsCarMapper.selectList(null);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(list));
//object
JSONObject jsonObject = new JSONObject();
jsonObject.put("data", jsonArray);
HttpEntity entity = new HttpEntity<>(jsonObject, headers);
// String json = restTemplate.postForObject("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", entity, String.class);
ResponseEntity<String> json = restTemplate.postForEntity("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", entity, String.class);
if (json != null){
/*JSONArray users = json.getJSONArray("data");
list = users.toJavaList(BisBasicsCar.class);*/
}
}
此处注意的有以下几点:
1、key/value传参要使用LinkedMultiValueMap而不是HashMap
2、笔者使用的json转换是借用alibaba的第三方包fastjson
3、server端要接收参数需要用@RequestBody注解,不然无法接收到参数
2、postForObject方法
先看下源码中关于postForObject有三种不同传参的方法
@Nullable
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Object[])uriVariables);
}
@Nullable
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters(), this.logger);
return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor, (Map)uriVariables);
}
@Nullable
public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType) throws RestClientException {
RequestCallback requestCallback = this.httpEntityCallback(request, responseType);
HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor(responseType, this.getMessageConverters());
return this.execute(url, HttpMethod.POST, requestCallback, responseExtractor);
}
参数可以是Json字符串,JavaBean对象,也可以是map,其中本质都是使用了HttpEntity对象
(一)传递Json字符串
传递Json字符串需要手动的将Json字符串添加到HttpEntity,具体做法如下:
public void test(){
//车辆表
List<BisBasicsCar> list = bisBasicsCarMapper.selectList(null);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(list));
//object
JSONObject jsonObject = new JSONObject();
jsonObject.put("data", jsonArray);
HttpEntity entity = new HttpEntity<>(jsonObject, headers);//@1
String json = restTemplate.postForObject("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", entity, String.class);
}
@1:将Json字符串添加到HttpEntity 对象中
(二)传递JavaBean
有两种做法,一种是手动把JavaBean添加到HttpEntity对象中,一种直接传JavaBean对象
public void test2(){
BisBasicsCar bisBasicsCar = new BisBasicsCar();
bisBasicsCar.setCarType("轿车");
bisBasicsCar.setDriver("司机王师傅");
bisBasicsCar.setLicenseNumber("沪A888888");
HttpHeaders headers = new HttpHeaders();
HttpEntity entity = new HttpEntity<>(bisBasicsCar, headers);//@1
String json = restTemplate.postForObject("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", entity, String.class);
}
public void test3(){
BisBasicsCar bisBasicsCar = new BisBasicsCar();
bisBasicsCar.setCarType("轿车");
bisBasicsCar.setDriver("司机王师傅");
bisBasicsCar.setLicenseNumber("沪A888888");
String json = restTemplate.postForObject("http://localhost:8099/basics/bisBasicsCar/synchronizationCar", bisBasicsCar, String.class);//@2
}
@1:手动将JavaBean加入到HttpEntity 对象中
@2:直接传JavaBean对象
为什么说本质上都是使用了HttpEntity对象呢?
是因为源码中有这样一段代码:
public HttpEntityRequestCallback(@Nullable Object requestBody, @Nullable Type responseType) {
super(responseType);
if (requestBody instanceof HttpEntity) {
this.requestEntity = (HttpEntity)requestBody;
} else if (requestBody != null) {
this.requestEntity = new HttpEntity(requestBody);
} else {
this.requestEntity = HttpEntity.EMPTY;
}
}
程序会自动判断,如果不是HttpEntity对象就手动添加一次
3、postForLocation
postForLocation也是提交新资源,提交成功之后,返回新资源的URI,postForLocation的参数和前面两种的参数基本一致,只不过该方法的返回值为Uri,这个只需要服务提供者返回一个Uri即可,该Uri表示新资源的位置。
然后看下列实际代码中会发现,最终还是使用了HttpEntity对象
public HttpEntityRequestCallback(@Nullable Object requestBody) {
this(requestBody, (Type)null);//@1
}
public HttpEntityRequestCallback(@Nullable Object requestBody, @Nullable Type responseType) {//@2
super(responseType);
if (requestBody instanceof HttpEntity) {
this.requestEntity = (HttpEntity)requestBody;
} else if (requestBody != null) {
this.requestEntity = new HttpEntity(requestBody);
} else {
this.requestEntity = HttpEntity.EMPTY;
}
}
Java多态的方法,但是还在@1的位置处调用了@2的方法