- 推荐序一
- 推荐序二
- 推荐序三
- 推荐语
- 前言
- 第1章 基础知识
- 第2章 微服务构建:Spring Boot
- 第3章 服务治理:Spring Cloud Eureka
- 第4章 客户端负载均衡:Spring Cloud Ribbon
- 第5章 服务容错保护:Spring Cloud Hystrix
- 第6章 声明式服务调用:Spring Cloud Feign
- 第7章 API网关服务:Spring Cloud Zuul
- 第8章 分布式配置中心:Spring Cloud Config
- 第9章 消息总线:Spring Cloud Bus
- 第10章 消息驱动的微服务:Spring Cloud Stream
- 附录 A Starter POMs
- 后记
RestTemplate 详解
在上一章中,我们已经通过引入Ribbon实现了服务消费者的客户端负载均衡功能,读者可以通过查看第3章中的“服务发现与消费”一节来获取实验示例。其中,我们使用了一个非常有用的对象RestTemplate。该对象会使用Ribbon的自动化配置,同时通过配置@LoadBalanced 还能够开启客户端负载均衡。之前我们演示了通过 RestTemplate实现了最简单的服务访问,下面我们将详细介绍 RestTemplate 针对几种不同请求类型和参数类型的服务调用实现。
GET请求
在RestTemplate中,对GET请求可以通过如下两个方法进行调用实现。
第一种:getForEntity函数。该方法返回的是ResponseEntity,该对象是Spring对HTTP请求响应的封装,其中主要存储了HTTP的几个重要元素,比如HTTP请求状态码的枚举对象httpStatus(也就是我们常说的404、500这些错误码)、在它的父类HttpEntity中还存储着HTTP请求的头信息对象HttpHeaders以及泛型类型的请求体对象。比如下面的例子,就是访问USER-SERVER服务的/user请求,同时最后一个参数didi会替换url中的{1}占位符,而返回的ResponseEntity对象中的body内容类型会根据第二个参数转换为String类型。
RestTemplate restTemplate=new RestTemplate();
ResponseEntity<String> responseEntity=restTemplate.getForEntity("http://USER-SERVICE/user? name={1}",String.class,"didi");
String body=responseEntity.getBody();
若我们希望返回的body是一个User对象类型,也可以这样实现:
RestTemplate restTemplate=new RestTemplate();
ResponseEntity<User> responseEntity=restTemplate.getForEntity("http://USER-SERVICE/user? name={1}",User.class,"didi");
User body=responseEntity.getBody();
上面的例子是比较常用的方法,getForEntity函数实际上提供了以下三种不同的重载实现。
- getForEntity(String url,Class responseType,Object...urlVariables):该方法提供了三个参数,其中 url 为请求的地址,responseType 为请求响应体body的包装类型,urlVariables为url中的参数绑定。GET请求的参数绑定通常使用url中拼接的方式,比如http://USER-SERVICE/user? name=didi,我们可以像这样自己将参数拼接到url中,但更好的方法是在url中使用占位符并配合 urlVariables 参数实现 GET 请求的参数绑定,比如 url 定义为http://USER-SERVICE/user? name={1},然后可以这样来调用:getForEntity("http://USER-SERVICE/user? name={1}",String.class,"didi"),其中第三个参数 didi 会替换 url 中的{1}占位符。这里需要注意的是,由于urlVariables 参数是一个数组,所以它的顺序会对应 url 中占位符定义的数字顺序。
- getForEntity(String url,Class responseType,Map urlVariables):该方法提供的参数中,只有 urlVariables 的参数类型与上面的方法不同。这里使用了Map类型,所以使用该方法进行参数绑定时需要在占位符中指定Map 中参数的key值,比如url定义为http://USER-SERVICE/user? name={name},在Map类型的urlVariables中,我们就需要put一个key为name的参数来绑定url中{name}占位符的值,比如:
RestTemplate restTemplate=new RestTemplate();
Map<String,String> params=new HashMap<>();
params.put("name","dada");
ResponseEntity<String> responseEntity=restTemplate.getForEntity("http://USER-SERVICE/user? name={name}",String.class,params);
- getForEntity(URI url,Class responseType):该方法使用URI对象来替代之前的url和urlVariables参数来指定访问地址和参数绑定。URI是JDK java.net包下的一个类,它表示一个统一资源标识符(Uniform Resource Identifier)引用。比如下面的例子:
RestTemplate restTemplate=new RestTemplate();
UriComponents uriComponents=UriComponentsBuilder.fromUriString(
"http://USER-SERVICE/user? name={name}")
.build()
.expand("dodo")
.encode();
URI uri=uriComponents.toUri();
ResponseEntity<String> responseEntity=restTemplate.getForEntity(uri,String.class).getBody();
更多关于如何定义一个URI的方法可以参见JDK文档,这里不做详细说明。
第二种:getForObject函数。该方法可以理解为对getForEntity的进一步封装,它通过HttpMessageConverterExtractor对HTTP的请求响应体body内容进行对象转换,实现请求直接返回包装好的对象内容。比如:
RestTemplate restTemplate=new RestTemplate();
String result=restTemplate.getForObject(uri,String.class);
当body是一个User对象时,可以直接这样实现:
RestTemplate restTemplate=new RestTemplate();
User result=restTemplate.getForObject(uri,User.class);
当不需要关注请求响应除 body 外的其他内容时,该函数就非常好用,可以少一个从Response中获取body的步骤。它与getForEntity函数类似,也提供了三种不同的重载实现。
- getForObject(String url,Class responseType,Object...urlVariables):与getForEntity的方法类似,url参数指定访问的地址,responseType参数定义该方法的返回类型,urlVariables参数为url中占位符对应的参数。
- getForObject(String url,Class responseType,Map urlVariables):在该函数中,使用Map类型的urlVariables替代上面数组形式的urlVariables,因此使用时在url中需要将占位符的名称与Map类型中的key一一对应设置。
- getForObject(URI url,Class responseType):该方法使用 URI 对象来替代之前的url和urlVariables参数使用。
POST请求
在RestTemplate中,对POST请求时可以通过如下三个方法进行调用实现。
第一种:postForEntity函数。该方法同GET请求中的getForEntity类似,会在调用后返回ResponseEntity<T>对象,其中T为请求响应的body类型。比如下面这个例子,使用postForEntity提交POST请求到USER-SERVICE服务的/user接口,提交的body内容为user对象,请求响应返回的body类型为String。
RestTemplate restTemplate=new RestTemplate();
User user=new User("didi",30);
ResponseEntity<String> responseEntity=
restTemplate.postForEntity("http://USER-SERVICE/user",user,String.class);
String body=responseEntity.getBody();
postForEntity函数也实现了三种不同的重载方法。
- postForEntity(String url,Object request,Class responseType,Object...uriVariables)
- postForEntity(String url,Object request,Class responseType,Map uriVariables)
- postForEntity(URI url,Object request,Class responseType)
这些函数中的参数用法大部分与 getForEntity 一致,比如,第一个重载函数和第二个重载函数中的 uriVariables 参数都用来对 url 中的参数进行绑定使用;responseType参数是对请求响应的body内容的类型定义。这里需要注意的是新增加的request参数,该参数可以是一个普通对象,也可以是一个HttpEntity对象。如果是一个普通对象,而非HttpEntity对象的时候,RestTemplate会将请求对象转换为一个HttpEntity对象来处理,其中Object就是request的类型,request内容会被视作完整的body来处理;而如果request是一个HttpEntity对象,那么就会被当作一个完成的http 请求对象来处理,这个 request 中不仅包含了 body 的内容,也包含了header的内容。
第二种:postForObject 函数。该方法也跟 getForObject 的类型类似,它的作用是简化postForEntity的后续处理。通过直接将请求响应的body内容包装成对象来返回使用,比如下面的例子:
RestTemplate restTemplate=new RestTemplate();
User user=new User("didi",20);
String postResult=restTemplate.postForObject("http://USER-SERVICE/user",user,String.class);
postForObject函数也实现了三种不同的重载方法:
- postForObject(String url,Object request,Class responseType,Object...uriVariables)
- postForObject(String url,Object request,Class responseType,Map uriVariables)
- postForObject(URI url,Object request,Class responseType)
这三个函数除了返回的对象类型不同,函数的传入参数均与postForEntity一致,因此可参考之前postForEntity的说明。
第三种:postForLocation函数。该方法实现了以POST请求提交资源,并返回新资源的URI,比如下面的例子:
User user=new User("didi",40);
URI responseURI=restTemplate.postForLocation("http://USER-SERVICE/user",user);
postForLocation函数也实现了三种不同的重载方法:
- postForLocation(String url,Object request,Object...urlVariables)
- postForLocation(String url,Object request,Map urlVariables)
- postForLocation(URI url,Object request)
由于postForLocation函数会返回新资源的URI,该URI就相当于指定了返回类型,所以此方法实现的POST请求不需要像postForEntity和postForObject那样指定responseType。其他的参数用法相同。
PUT请求
在RestTemplate中,对PUT请求可以通过put方法进行调用实现,比如:
RestTemplate restTemplate=new RestTemplate();
Long id=10001L;
User user=new User("didi",40);
restTemplate.put("http://USER-SERVICE/user/{1}",user,id);
put函数也实现了三种不同的重载方法:
- put(String url,Object request,Object...urlVariables)
- put(String url,Object request,Map urlVariables)
- put(URI url,Object request)
put函数为void类型,所以没有返回内容,也就没有其他函数定义的responseType参数,除此之外的其他传入参数定义与用法与postForObject基本一致。
DELETE请求
在RestTemplate中,对DELETE请求可以通过delete方法进行调用实现,比如:
RestTemplate restTemplate=new RestTemplate();
Long id=10001L;
restTemplate.delete("http://USER-SERVICE/user/{1}",id);
delete函数也实现了三种不同的重载方法:
- delete(String url,Object...urlVariables)
- delete(String url,Map urlVariables)
- delete(URI url)
由于我们在进行REST请求时,通常都将DELETE请求的唯一标识拼接在url中,所以DELETE请求也不需要request的body信息,就如上面的三个函数实现一样,非常简单。url指定DELETE请求的位置,urlVariables绑定url中的参数即可。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论