RestTemplate用法浅谈
一、概述
前一阵子做项目用到了跨服务调用,springboot里面的一个小玩意,以前也用过几次,但是对其理解不够深,现在又用到了,就在网上找了一些资料,给大家分享一下。
spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅的调用RESTful服务的方式。
在Spring应用程序中访问第三方REST服务与使用Spring RestTemplate类有关。RestTemplate类的设计原则与许多其他Spring *模板类(例如JdbcTemplate、JmsTemplate)相同,为执行复杂任务提供了一种具有默认行为的简化方法。
RestTemplate默认依赖JDK提供http连接的能力(HttpURLConnection),如果有需要的话也可以通过setRequestFactory方法替换为例如 Apache HttpComponents、Netty或OkHttp等其它HTTP library。
考虑到RestTemplate类是为调用REST服务而设计的,因此它的主要方法与REST的基础紧密相连就不足为奇了,后者是HTTP协议的方法:HEAD、GET、POST、PUT、DELETE和OPTIONS。例如,RestTemplate类具有headForHeaders()、getForObject()、postForObject()、put()和delete()等方法。
注:还有几个getForEntity和getForObject、postForEntity和postForObject,这两个方法用途其实是一样的,但是用法有区别:
getForObject函数实际上是对getForEntity函数的进一步封装,如果你只关注返回的消息体的内容,对其他信息都不关注,此时可以使用getForObject。
1.使用Object时还需要判断返回的类型,而使用Entity则表示已经确认了rest接口的返回类型
2.使用Object时使用的是URI链接
此用法具体请参考http://www.voidcn.com/article/p-uzrwndmi-bex.html
二、详情
本文章仅对Object方法进行详解,entity暂不做介绍
RestTemplate包含以下几个部分:
·HttpMessageConverter 对象转换器
·ClientHttpRequestFactory 默认是JDK的HttpURLConnection
·ResponseErrorHandler 异常处理
·ClientHttpRequestInterceptor 请求拦截器
常规配置
这一般都是配置连接服务的时候要用到的拦截一系列的玩意,很少有用到,现在用到的是来权限框架等,这里就不做过多的解释,直接拷贝过来的代码,大家看一下就行,能用到的希望有所帮助,直接介绍方法。
public MyRestClientService(RestTemplateBuilder restTemplateBuilder) {
this.restTemplate = restTemplateBuilder
.basicAuthorization("username", "password")
.setConnectTimeout(3000)
.setReadTimeout(5000)
.rootUri("http://api.example.com/")
.build();
}
ClientHttpRequestInterceptor
学习使用带有Spring RestTemplate的ClientHttpRequestInterceptor,以Spring AOP风格记录请求和响应头和主体。
拦截器记录请求和响应
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StreamUtils;
import java.io.IOException;
import java.nio.charset.Charset;
public class RequestResponseLoggingInterceptor implements ClientHttpRequestInterceptor {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException
{
logRequest(request, body);
ClientHttpResponse response = execution.execute(request, body);
logResponse(response);
//Add optional additional headers
response.getHeaders().add("headerName", "VALUE");
return response;
}
private void logRequest(HttpRequest request, byte[] body) throws IOException
{
if (log.isDebugEnabled())
{
log.debug("===========================request begin================================================");
log.debug("URI : {}", request.getURI());
log.debug("Method : {}", request.getMethod());
log.debug("Headers : {}", request.getHeaders());
log.debug("Request body: {}", new String(body, "UTF-8"));
log.debug("==========================request end================================================");
}
}
private void logResponse(ClientHttpResponse response) throws IOException
{
if (log.isDebugEnabled())
{
log.debug("============================response begin==========================================");
log.debug("Status code : {}", response.getStatusCode());
log.debug("Status text : {}", response.getStatusText());
log.debug("Headers : {}", response.getHeaders());
log.debug("Response body: {}", StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
log.debug("=======================response end=================================================");
}
}
}
注册ClientHttpRequestInterceptor
@Bean
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(newBufferingClientHttpRequestFactory(clientHttpRequestFactory()));
restTemplate.setMessageConverters(Collections.singletonList(mappingJacksonHttpMessageConverter()));
restTemplate.setInterceptors( Collections.singletonList(newRequestResponseLoggingInterceptor()) );
return restTemplate;
}
三、使用详情
先看一下Get请求方法
这个方法有两参数和三个参数的
两个参数:
String result = restTemplate.getForObject("http://www.baidu.com", String.class);
三个参数:
String result = restTemplate.getForObject("http://www.baidu.com", String.class, map);
解释一下参数,当第一个参数是请求链接,第二个参数是responseType也就是返回参数类型(没有返回参数可以写null,但是必须要写,不然会报错,并且这里必须跟接收参数保持一致),第三个参数写请求接口时的附带参数列表,如果没有可不写(如两参数)。
如果请求接口做了权限控制,需要添加请求头
private static void getEmployees(){
final String uri = "http://www.baidu.com";
//实例化模板
RestTemplate restTemplate = new RestTemplate();
//实例化请求头实体
HttpHeaders headers = new HttpHeaders();
//添加请求头参数
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
ResponseEntity<String> result = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
}
post请求
用法和Get一样,只是对参数顺序做了调整
·方法的第一参数表示要调用的服务的地址
·方法的第二个参数表示上传的参数
·方法的第三个参数表示返回的消息体的数据类型
postForLocation
postForLocation也是提交新资源,提交成功之后,返回新资源的URI,postForLocation的参数和前面两种的参数基本一致,只不过该方法的返回值为Uri,这个只需要服务提供者返回一个Uri即可,该Uri表示新资源的位置。
put请求
在RestTemplate中,PUT请求可以通过put方法调用,put方法的参数和前面介绍的postForEntity方法的参数基本一致,只是put方法没有返回值而已。举一个简单的例子,如下:
@RequestMapping("/put")
public void put() {
Student stu = new Student();
Student.setName("张三");
//book对象是我要提交的参数,最后的9用来替换前面的占位符{id}
restTemplate.put("http://SERVICE/getStu3/{id}", stu , 9);
}
delete请求
delete方法也有几个重载的方法,不过重载的参数和前面基本一致,不过多详解了。
四、总结
以上就是我对restTemplate远程请求接口的理解和用法,希望可以帮到大家,写这些东西,只是为了更好的记住这些用法,不喜勿喷,有什么建议欢迎留言,多总结,多修改,才能成长,小白一枚,还望大佬多多指教