restTemplate方法使用

先看看RestTemplate类的Outline: 

RestTemplateç±»
最上面的成员和下面的几个构造方法可以先大概看一下。就是选择性的去构造消息转换器,用来接收和传递相应的类型的HTTP请求数据。 
下面的是重点,各种HTTP请求如下: 
GET请求的有: 

GET请æ±
先看前端3个getForObject方法。重载的3个方法,其区别就是传参数不一样,返回的内容都是一样的。我们可以看一下这3个方法的接口定义(RestTemplate类是实现了RestOperations接口)可以看到返回的是一样的,都是 返回 the converted object。 

RestOperationsæ¥å£å®ä¹
对于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<String, Object> resultMap = restTemplate.getForObject(url, Map.class,"123456","xiao ming");
调用的是<T> T getForObject(String url, Class<T> responseType, Object... uriVariables)方法。 
接收http请求的地方写成:

@GetMapping(value = "/testAccept/{id}/kid/{name}")
public Map<String, Object> testAccept(@PathVariable String id,@PathVariable String name){
    Map<String, Object> ret = Maps.newHashMap();
    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<String, Object> requestMap = Maps.newHashMap();
requestMap.put("id", "123456");
requestMap.put("name", "xiao ming");
String url = "http://www.xxx.com/testAccept/kid?id={id}&name={name}";
Map<String, Object> resultMap = restTemplate.getForObject(url, Map.class,requestMap);

调用的是<T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)方法。 
接收http请求的地方写成:

@GetMapping(value = "/testAccept/kid")
public Map<String, Object> testAccept(@RequestParam String id,@RequestParam String name){
    Map<String, Object> ret = Maps.newHashMap();
    ret.put("id", id);
    ret.put("name", name);
    return ret;
}

@RequestParam注解表示2个都是请求的参数。 
对于不带参数的get请求,三种getForObject方法都可以调用:

String url = "http://www.xxx.com/testAccept/kid";
Map<String, Object> resultMap = restTemplate.getForObject(url, Map.class);
Map<String, Object> resultMap1 = restTemplate.getForObject(url, Map.class);
URI uri = URI.create(url);
Map<String, Object> resultMap2 = restTemplate.getForObject(uri, Map.class);

区别就是后面一个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: 
 POST请æ±çä¹ä¸ªæ¹æ³
看一看这些方法的接口定义: 
首先是三个postForLocation,注意这三个方法返回的是一个URI。看看接口定义: 

postForLocationçæ¥å£å®ä¹

三个接口都通过给定的数据发送一个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<String> requestEntity = new HttpEntity<String>(body , headers);
restTemplate.postForLocation(URI.create("http://www.xxx.com/test"), requestEntity);

当然,不需要传HttpEntity对象的时候一样可以传其他对象。 
再看这三个方法的实现: 

postForLocationçå®ç°

 

都是解析不同的参数,然后调用RestTemplate的execute方法,返回一个HttpHeaders,然后取其中的Location返回。Location字段一般用于重定向接受者到一个新的位置。例如:客户端所请求的页面已不存在原先的位置,为了让客户端重定向到这个页面新的位置,服务 器端可以发回Location响应报头后使用重定向语句,让客户端去访问新的域名所对应的服务器上的资源。当我们在使用重定向语句(如HttpServletResponse的sendRedirect方法)的时候,服务器 端向客户端发回的响应报头中,就会有Location响应报头域。顺便看一下HttpHeaders中的getLocation方法: 
 getLocationæ¹æ³
就是将重定向的那个新的位置转成一个URI地址,没有重定向就返回一个null。 
接下来是三个postForObject方法,接口定义: 

postForObjectæ¥å£å®ä¹

与上面的post请求一样,都是psot来创建资源,请求参数与上面的三个接口也是类似的,唯一一个不同就是多一个指定HTTP请求的返回的数据类型(这一点与getForObject是一样的)。返回的是一个泛型,具体类型根据请求参数Class<T> responseType来确定。 
postForObject方法的重点来了: 
对于post方法来说,请求参数可以放到请求url里面(uriVariables),也可以放到http的body里面,当然一般来说post的数据放到body里面比较正规,也比较好,因为这样数据相对不会暴露。但是有些比较简单的无关紧要的数据放到url里面传也不是不可以。所以下面重点说一下postForObject的传参方式:

1. 参数放在url里面

        调用` <T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables) throws RestClientException;`方法。
如:Map<String, Object> object = restTemplate.postForObject("http://www.xxx.com/testSend?name={name}&gender={gender}", null, Map.class,"xiao ming",1);

放在uriVariables里面传参数,与getForObject其实是类似的,一定要将指定参数,如此处的name和gender。因为body里面不传值,所以此处的第二个参数传个null,这个null不能省略。 
接收http请求的地方:

@PostMapping(value = "/testAccept")
public Map<String, Object> testAccept(@RequestParam String name,@RequestParam int gender){
    Map<String, Object> ret = Maps.newHashMap();
    User user= new User ();
    user.setName(name);
    user.setGender(gender);
    userService.save(user);
    ret.put("user", user);
    return ret;
}
或者参数放在url路径上,如:

Map<String, Object> object = restTemplate.postForObject("http://www.xxx.com/testSend/{name}/gender/{gender}", null, Map.class,"xiao ming",1);
接收http请求的地方:

@PostMapping(value = "/testSend/{name}/gender/{gender}")
public Map<String, Object> testAccept(@PathVariable String name,@PathVariable int gender){
    Map<String, Object> ret = Maps.newHashMap();
    User user= new User ();
    user.setName(name);
    user.setGender(gender);
    userService.save(user);
    ret.put("user", user);
    return ret;
}
注意两点, 一是请求的url的地方加占位,二是参数的注解是@PathVariable,表示是路径上的参数。

调用<T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;方法。 
与调用上一个方法其实是一样的,唯一的区别就是上面的参数是直接一个个列出来,面这个方法是将参数封到一个map里面,注意,map里面的key一定要与参数里面的占位参数一致。如上面2种参数的写法,如果调用这个方法就是:

Map<String,Object> requestMap = Maps.newHashMap();
requestMap.put("name", "xiao ming");
requestMap.put("gender", 1);
Map<String, Object> object = restTemplate.postForObject("http://www.xxx.com/testSend?name={name}&gender={gender}", null, Map.class,requestMap);
或者参数在路径上:

Map<String,Object> requestMap = Maps.newHashMap();
requestMap.put("name", "xiao ming");
requestMap.put("gender", 1);
Map<String, Object> object = restTemplate.postForObject("http://www.xxx.com/testSend/{name}/gender/{gender}", null, Map.class,requestMap);

对于这两种写法,在接收HTTP请求的地方写法与上面对应的2种写法是一样的。

2.参数只放在body里面

参数只放在body里面的话,三个postForObject方法就没有多大区别了: 

å»ææåä¸ä¸ªåæ°çpostForObjectæ¹æ³

第一个和第二个一样了,与第三个的区别就是一个是String的url一个是url,区别不计。看写法:

HttpHeaders headers = new HttpHeaders(); // http请求头
headers.setContentType(MediaType.APPLICATION_JSON_UTF8); // 请求头设置属性  
Map<String,Object> body = Maps.newHashMap(); // 请求body
body.put("name", "xiao ming");
body.put("gender", 1);
HttpEntity<Map<String,Object>> requestEntity = new HttpEntity<Map<String,Object>>(body,headers);
Map<String, Object> object = restTemplate.postForObject("http://www.xxx.com/testSend", requestEntity, Map.class);
注意点我们看HttpEntity类的构造方法: 
 HttpEntityç±»çæé æ¹æ³
4个构造方法可以选择要或不要headers和body,花式构造HttpEntity。且body参数是泛型,可以传各种类型的body。 
在接收此HTTP请求的地方,只需要用@RequestBody来接收参数即可:

@PostMapping(value = "/testSend")
public Map<String, Object> testAccept(@RequestBody Map<String, Object> request){
    Map<String, Object> ret = Maps.newHashMap();
    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<T>的T的类型一致。上面的例子都是用的Map<String,Object>。

3.混合传值url和body一个地方放一点参数。 
直接上例子:

HttpHeaders headers = new HttpHeaders(); // http请求头
headers.setContentType(MediaType.APPLICATION_JSON_UTF8); // 请求头设置属性 
HttpEntity<Integer> requestEntity = new HttpEntity<Integer>(1,headers);
Map<String, Object> object = restTemplate.postForObject("http://www.xxx.com/testSend?name={name}", requestEntity, Map.class,"xiao ming");
接收HTTP请求的地方 :

@PostMapping(value = "/testSend")
public Map<String, Object> testAccept(@RequestBody int request,@RequestParam String name){
    Map<String, Object> ret = Maps.newHashMap();
    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<T> responseType参数),一般来说用Map的比较多。 
再接下来是三个postForEntity方法,接口定义: 

ä¸ä¸ªpostForEntityæ¥å£å®ä¹

与上面的postForObject的传参方法是一模一样的,唯一不同的就是postForObject返回的是自己指定的数据,相当于只返回body,而postForEntity返回的是一个ResponseEntity对象,对象包括了http响应的headers、body等信息。 
至于写法,和postForEntity一毛一样,不再写了。至此post方法的写完了

PUT、PATCH、DELETE、OPTIONS请求的有: 
 putãpatchãdelete请æ±
put、patch、delete请求比较简单,就放在一起了。 
先看put的接口定义: 

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操作不是幂等的,所以不能反复的去调用此方法来做某一个更新,另外patch方法与put方法做更新的区别需要说明一下:put是将对象丢过去,没有就创建,有就全体更新,面patch是只将对象的一个部份丢过去,并更新丢过去的那一部份。patch方法目前用的不多。 
再一个是delete的方法了,看接口定义: 

deleteæ¥å£å®ä¹

感觉delete的没什么说的,与上面的一样,3种传参方式去删除指定的URL上的资源。 
最后再提一嘴OPTIONS请求。 
OPTIONS 方法请求 Web 服务器告知其支持的各种功能。可以询问服务器通常支持哪些方法,或者对某些特殊资源支持哪些方法。因为有些服务器可能只支持对一些特殊类型的对象使用特定的操作。 
看例子:

Set<HttpMethod> allow = restTemplate.optionsForAllow("http://www.xxx.com/testSend");

è¿å示ä¾
 
方法返回服务器支持的方法。这几个方法一般不会主动去调用,大概知道用处就行。

下面要重点说看一下exchange的系列方法了 
exchange的请求的有: 

exchangeçç³»åæ¹æ³
 
总共有8个exchange方法!!!所有的方法全部都是返回的ResponseEntity<T>,与前面的一样,就不多说了。 
先看前面3个exchange方法 

åé¢3个exchangeæ¥å£å®ä¹

感觉与前面的postForEntity和getForEntity很类似,是吧。对比一下:

// GET
<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
// POST
<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
// EXCHANGE
<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,Class<T> responseType, Object... uriVariables)
可以看出来相同点: 
1、返回类型都是ResponseEntity<T>; 
2、第一个参数都是String类型的url; 
3、最后的2个参数都是Class<T> responseType, Object... uriVariables分别是返回值的具体类型和可变参数。 
不同点: 
1、对于post请求,中间可以多传一下Object request; 
2、对于ecchange方法,此方法的http请求类型要自己去指定HttpMethod method,且可以多传一个HttpEntity。 
结论:1、exchange方法可以当get请求发也可以当post请求来发,甚至可以当其他的(put、patch等)请求来发。HttpMethod是一个枚举,如下所示,可以看到exchange方法可以发常见的8种http请求。例如get请求:HttpMethod.GET。 

ecchangeæ¹æ³ä¸­ä¼ çhttp method

2、exchange的传参方式除了指定HttpMethod之外,其他参数传递与getForEntity、postForEntity基本是一样的。如:

ResponseEntity<Map> exchange = restTemplate.exchange("http://www.xxx.com/testSend", HttpMethod.GET, null, Map.class, 90,2019);
再看中间的3个exchange方法: 

中é´ç3个exchange

可以看到中间的3个方法与前面的3个方法唯一不相同的就是指定返回类型了,前面3个方法都是Class<T> responseType而此处的3个方法都是ParameterizedTypeReference<T> responseType,其他的地方完全没有区别。这样的话我们就来看看这个ParameterizedTypeReference<T>是个什么东西(将光标放到类上面,然后按F2键): 

ParameterizedTypeReference<T>ç±»

该类的目的是启用泛型类型的捕获和传递。为了捕获泛型类型并在运行时保留它,您需要创建一个子类如下:

ParameterizedTypeReference<List<String>> typeRef = new ParameterizedTypeReference<List<String>>(){};
顺便说一下ParameterizedTypeReference<T>是一个抽象类,另外这个类根据名字我们其实可以大概可以猜到他的作用:参数化类型引用。于是我们可以这样写:

ParameterizedTypeReference<List<UserVO>> myBean = new ParameterizedTypeReference<List<UserVO>>() {};
ResponseEntity<List<UserVO>> exchange = restTemplate.exchange("http://www.xxx.com/testSend", HttpMethod.GET, null, myBean, 90,2019);
当要查询一个List类型的bean对象的时候,之前的Class<T> responseType类型的返回就有点力不从心了,因为我们在使用Class<T> responseType的时候只能定义到List层面,不知道List里面的是什么结构。使用ResponseEntity<List<UserVO>>后,我们可以在接收请求处定义一个与请求的bean数据结构一模一样的一个VO(value object),例如此处是查询一个User的List,我们在发送请求处定义一个与User数据结构一模一样的UserVO来接收List<User>,这样结果就更好处理。 
最后剩下的2个exchange方法: 

æå2个exchangeæ¥å£å®ä¹

可以看到最后这2个exchange接口都只传2个参数,第一个都是RequestEntity<?> requestEntity,第二个参数是Class<T> responseType或ParameterizedTypeReference<T> responseType。第二个参数的区别与作用和前面的2组exchange方法的参数一样不用多说了。而第一个参数,我们看他的说明:@param requestEntity the entity to write to the request是一个Http请求的entity。 

RequestEntityç±»
 
看到RequestEntity的几个成员:

    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 
 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RestTemplate是Spring Framework提供的一个用于访问Rest服务的客户端工具,它封装了一些常用的HTTP请求操作,比如GET、POST等。使用RestTemplate可以方便地发送HTTP请求,并能够自动将响应转换成指定的对象类型。下面是RestTemplate使用方法: 1. 创建RestTemplate对象 RestTemplate对象可以通过直接实例化或者通过注入的方式来创建。直接实例化方式如下: ``` RestTemplate restTemplate = new RestTemplate(); ``` 2. 发送HTTP请求 RestTemplate支持多种HTTP请求方法,比如GET、POST、PUT、DELETE等。以下是发送GET请求的示例代码: ``` String url = "http://example.com/api/users/{userId}"; Map<String, String> uriVariables = new HashMap<>(); uriVariables.put("userId", "123"); User user = restTemplate.getForObject(url, User.class, uriVariables); ``` 其中,url为请求的URL,uriVariables为请求参数,User.class为响应结果需要转换的类型。其他HTTP请求方法也类似,只需要替换对应的方法名即可。 3. 处理响应结果 RestTemplate支持多种方式处理响应结果,比如将响应结果转换成Java对象、将响应结果转换成JSON字符串等。以下是将响应结果转换成Java对象的示例代码: ``` String url = "http://example.com/api/users/{userId}"; Map<String, String> uriVariables = new HashMap<>(); uriVariables.put("userId", "123"); User user = restTemplate.getForObject(url, User.class, uriVariables); ``` 其中,url为请求的URL,uriVariables为请求参数,User.class为响应结果需要转换的类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值