先看看RestTemplate类的Outline:
最上面的成员和下面的几个构造方法可以先大概看一下。就是选择性的去构造消息转换器,用来接收和传递相应的类型的HTTP请求数据。
下面的是重点,各种HTTP请求如下:
GET请求的有:
先看前端3个getForObject方法。重载的3个方法,其区别就是传参数不一样,返回的内容都是一样的。我们可以看一下这3个方法的接口定义(RestTemplate类是实现了RestOperations接口)可以看到返回的是一样的,都是 返回 the converted object。
对于get方法,如果有请求参数的话,一般是2种传参数的方式:
1、参数是url路径上,如:http://www.xxx.com/testAccept/{id}/kid/{name}。此时使用restTemplate.getForObject可以写成
String url = "http://www.xxx.com/testAccept/{id}/kid/{name}";
Map
调用的是
接收http请求的地方写成:
@GetMapping(value = "/testAccept/{id}/kid/{name}")
public Map
Map
ret.put("id", id);
ret.put("name", name);
return ret;
}
@PathVariable注解表示2个参数都是url路径上的参数。
2、参数跟在url路径后面,如http://www.xxx.com/testAccept/kid?id={id}&name={name}。此时使用restTemplate.getForObject可以写成:
Map
requestMap.put("id", "123456");
requestMap.put("name", "xiao ming");
String url = "http://www.xxx.com/testAccept/kid?id={id}&name={name}";
Map
调用的是
接收http请求的地方写成:
@GetMapping(value = "/testAccept/kid")
public Map
Map
ret.put("id", id);
ret.put("name", name);
return ret;
}
@RequestParam注解表示2个都是请求的参数。
对于不带参数的get请求,三种getForObject方法都可以调用:
String url = "http://www.xxx.com/testAccept/kid";
Map
Map
URI uri = URI.create(url);
Map
区别就是后面一个getForObject方法第一个参数传的是个uri,前面2个传的都是String。简单的将String转成URI也是一样。
注意:第三个方法虽然少一个接收参数,但是不代表这个方法不能传参数,因为第一个参数是个URI是要自己去构造的。
然后是3个getForEntity方法,这三个重载的方法与上面3个getForObject方法大同小异,我们可以看一下这3个方法的接口定义,与上面的一样:
getForEntity与getForObject最大的区别就在于返回内容不一样:
getForEntity返回的是一个ResponseEntity,而getForObject返回的就只是返回内容。getForObject的返回相当于只返回http的body部份而getForEntity的返回是返回全部信息:
一般来说一是取status判断请求是否成功,成功则去取body里面的内容。
getForEntity请求参数的写法和接收参数的写法与getForObject是一样的,不赘述。
POST请求的有:
再接下来是POST请求。POST请求的9个方法,3个一组,postForLocation、postForObject、postForEntity:
看一看这些方法的接口定义:
首先是三个postForLocation,注意这三个方法返回的是一个URI。看看接口定义:
三个接口都通过给定的数据发送一个post请求来创建资源,然后返回一个HTTP 头。三个接口可以用不同的方式去给URI传参数,与上面的传参方法一样。每个接口都有这样一句解释:The {@code request} parameter can be a {@link HttpEntity} in order to add additional HTTP headers to the request. 解释了参数Object request的通常用法。如果想要在HTTP header里面加点什么东西(比如编码方式等)可以在此处传一个HttpEntity对象。如:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8); // 在header里面设置编码方式
String body = "xiao ming";
HttpEntity
restTemplate.postForLocation(URI.create("http://www.xxx.com/test"), requestEntity);
当然,不需要传HttpEntity对象的时候一样可以传其他对象。
再看这三个方法的实现:
都是解析不同的参数,然后调用RestTemplate的execute方法,返回一个HttpHeaders,然后取其中的Location返回。Location字段一般用于重定向接受者到一个新的位置。例如:客户端所请求的页面已不存在原先的位置,为了让客户端重定向到这个页面新的位置,服务 器端可以发回Location响应报头后使用重定向语句,让客户端去访问新的域名所对应的服务器上的资源。当我们在使用重定向语句(如HttpServletResponse的sendRedirect方法)的时候,服务器 端向客户端发回的响应报头中,就会有Location响应报头域。顺便看一下HttpHeaders中的getLocation方法:
就是将重定向的那个新的位置转成一个URI地址,没有重定向就返回一个null。
接下来是三个postForObject方法,接口定义:
与上面的post请求一样,都是psot来创建资源,请求参数与上面的三个接口也是类似的,唯一一个不同就是多一个指定HTTP请求的返回的数据类型(这一点与getForObject是一样的)。返回的是一个泛型,具体类型根据请求参数Class
postForObject方法的重点来了:
对于post方法来说,请求参数可以放到请求url里面(uriVariables),也可以放到http的body里面,当然一般来说post的数据放到body里面比较正规,也比较好,因为这样数据相对不会暴露。但是有些比较简单的无关紧要的数据放到url里面传也不是不可以。所以下面重点说一下postForObject的传参方式:
1. 参数放在url里面
调用`
如:Map
放在uriVariables里面传参数,与getForObject其实是类似的,一定要将指定参数,如此处的name和gender。因为body里面不传值,所以此处的第二个参数传个null,这个null不能省略。
接收http请求的地方:
@PostMapping(value = "/testAccept")
public Map
Map
User user= new User ();
user.setName(name);
user.setGender(gender);
userService.save(user);
ret.put("user", user);
return ret;
}
或者参数放在url路径上,如:
Map
接收http请求的地方:
@PostMapping(value = "/testSend/{name}/gender/{gender}")
public Map
Map
User user= new User ();
user.setName(name);
user.setGender(gender);
userService.save(user);
ret.put("user", user);
return ret;
}
注意两点, 一是请求的url的地方加占位,二是参数的注解是@PathVariable,表示是路径上的参数。
调用
与调用上一个方法其实是一样的,唯一的区别就是上面的参数是直接一个个列出来,面这个方法是将参数封到一个map里面,注意,map里面的key一定要与参数里面的占位参数一致。如上面2种参数的写法,如果调用这个方法就是:
Map
requestMap.put("name", "xiao ming");
requestMap.put("gender", 1);
Map
或者参数在路径上:
Map
requestMap.put("name", "xiao ming");
requestMap.put("gender", 1);
Map
对于这两种写法,在接收HTTP请求的地方写法与上面对应的2种写法是一样的。
2.参数只放在body里面
参数只放在body里面的话,三个postForObject方法就没有多大区别了:
第一个和第二个一样了,与第三个的区别就是一个是String的url一个是url,区别不计。看写法:
HttpHeaders headers = new HttpHeaders(); // http请求头
headers.setContentType(MediaType.APPLICATION_JSON_UTF8); // 请求头设置属性
Map
body.put("name", "xiao ming");
body.put("gender", 1);
HttpEntity
@PostMapping(value = "/testSend")
public Map
Map
User user= new User();
user.setName((String)request.getOrDefault("name", null));
user.setGender((int)request.getOrDefault("gender", 0));
userService.save(user);
ret.put("user", user);
return ret;
}
注意:@RequestBody 注解的接收参数的类型要与请求的HttpEntity
3.混合传值url和body一个地方放一点参数。
直接上例子:
HttpHeaders headers = new HttpHeaders(); // http请求头
headers.setContentType(MediaType.APPLICATION_JSON_UTF8); // 请求头设置属性
HttpEntity
Map
接收HTTP请求的地方 :
@PostMapping(value = "/testSend")
public Map
Map
User user= new User();
user.setGender(request);
user.setName(name);
userService.save(user);
ret.put("user", user);
return ret;
}
一个参数从url上取,一个参数从httpEntity的body里面取,是不是感觉怪怪的?but这样写一样可以取到值。但是不建议这样传值。
此外,postForObject方法的返回类型也是在发请求时自己定义的(方法的Class
再接下来是三个postForEntity方法,接口定义:
与上面的postForObject的传参方法是一模一样的,唯一不同的就是postForObject返回的是自己指定的数据,相当于只返回body,而postForEntity返回的是一个ResponseEntity对象,对象包括了http响应的headers、body等信息。
至于写法,和postForEntity一毛一样,不再写了。至此post方法的写完了
PUT、PATCH、DELETE、OPTIONS请求的有:
put、patch、delete请求比较简单,就放在一起了。
先看put的接口定义:
通过put方法用给定的对象来创建或者更新一个资源,请求参数与postForObject也是一毛一样,写法也是一样,不多说了,只说一句这3个put方法都是无返回,所以建议不用于创建操作。
还有一点要说明的是PUT操作是幂等的。关于幂等性,定义是:Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request.说白了就是不管你请求多少次结果都是一样的。
再是patch的接口定义:
通过patch方法用给定的对象来更新一个资源并返回。与上面的方法一样,参数和写法都是一样的,不用多说了。强调一下的是patch操作不是幂等的,所以不能反复的去调用此方法来做某一个更新,另外patch方法与put方法做更新的区别需要说明一下:put是将对象丢过去,没有就创建,有就全体更新,面patch是只将对象的一个部份丢过去,并更新丢过去的那一部份。patch方法目前用的不多。
再一个是delete的方法了,看接口定义:
感觉delete的没什么说的,与上面的一样,3种传参方式去删除指定的URL上的资源。
最后再提一嘴OPTIONS请求。
OPTIONS 方法请求 Web 服务器告知其支持的各种功能。可以询问服务器通常支持哪些方法,或者对某些特殊资源支持哪些方法。因为有些服务器可能只支持对一些特殊类型的对象使用特定的操作。
看例子:
Set
方法返回服务器支持的方法。这几个方法一般不会主动去调用,大概知道用处就行。
下面要重点说看一下exchange的系列方法了
exchange的请求的有:
总共有8个exchange方法!!!所有的方法全部都是返回的ResponseEntity
先看前面3个exchange方法
感觉与前面的postForEntity和getForEntity很类似,是吧。对比一下:
// GET
// POST
// EXCHANGE
可以看出来相同点:
1、返回类型都是ResponseEntity
2、第一个参数都是String类型的url;
3、最后的2个参数都是Class
不同点:
1、对于post请求,中间可以多传一下Object request;
2、对于ecchange方法,此方法的http请求类型要自己去指定HttpMethod method,且可以多传一个HttpEntity。
结论:1、exchange方法可以当get请求发也可以当post请求来发,甚至可以当其他的(put、patch等)请求来发。HttpMethod是一个枚举,如下所示,可以看到exchange方法可以发常见的8种http请求。例如get请求:HttpMethod.GET。
2、exchange的传参方式除了指定HttpMethod之外,其他参数传递与getForEntity、postForEntity基本是一样的。如:
ResponseEntity
再看中间的3个exchange方法:
可以看到中间的3个方法与前面的3个方法唯一不相同的就是指定返回类型了,前面3个方法都是Class
该类的目的是启用泛型类型的捕获和传递。为了捕获泛型类型并在运行时保留它,您需要创建一个子类如下:
ParameterizedTypeReference> typeRef = new ParameterizedTypeReference
>(){};
顺便说一下ParameterizedTypeReference
ParameterizedTypeReference> myBean = new ParameterizedTypeReference
>() {};
ResponseEntity> exchange = restTemplate.exchange("http://www.xxx.com/testSend", HttpMethod.GET, null, myBean, 90,2019);
当要查询一个List类型的bean对象的时候,之前的Class>后,我们可以在接收请求处定义一个与请求的bean数据结构一模一样的一个VO(value object),例如此处是查询一个User的List,我们在发送请求处定义一个与User数据结构一模一样的UserVO来接收List
最后剩下的2个exchange方法:
可以看到最后这2个exchange接口都只传2个参数,第一个都是RequestEntity> requestEntity,第二个参数是Class
private final HttpMethod method;
private final URI url;
private final Type type;
和他的这几个构造方法就知道,其实这里的RequestEntity>实际上就是将前面的几个exchange方法中的url、method、responseType等几个参数封装起来了,本质上还是一样的。
至此RestTemplate中的Http请求方法的使用就都介绍完了。
下面将这些方法大概的做一个总结,总结就根据实际需求来分类,分为4类查询,新增、修改、删除:
约定:所有的方法中只对url是String类型的方法做分类和总结,因为一个是请求过程中的url常见的都是String,二是String类型的url可以手动的转在URI.所以所有的URI为参数的方法都当重复方法,不再做分类和总结。
本文是自己学习restemplate时,网上看到的一篇博文,coopy过来当做笔记,读者有兴趣可以查看原文,原文地址为:
https://blog.csdn.net/u012843361/article/details/79893638