RestTemplate 教程
原文链接:https://www.jianshu.com/p/35aca2e31f06
一、概述
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()等方法。
二、创建RestTemplate
所使用的springboot.version==2.2.x.RELEASE
1、方法一
设置一下超时时间、基本认证信息等
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
//.basicAuthentication("username", "password")
// .setConnectTimeout(Duration.ofSeconds(3))
// .setReadTimeout(Duration.ofSeconds(5))
// .rootUri("http://api.test.com/")
.build();
}
2、方法二
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
3、添加拦截器(ClientHttpRequestInterceptor)
有时候我们需要对请求做一些通用的拦截设置,这就可以使用拦截器进行处理。拦截器需要我们实现org.springframework.http.client.ClientHttpRequestInterceptor接口自己写。
3.1、使用拦截器
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.additionalInterceptors(new CustomClientHttpRequestInterceptor())
.build();
}
3.2、拦截器示例
import com.google.common.base.Charsets;
import lombok.extern.slf4j.Slf4j;
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;
@Slf4j
public class CustomClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(
HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
//打印请求明细
logRequestDetails(request, body);
ClientHttpResponse response = execution.execute(request, body);
//打印响应明细
logResponseDetails(response);
return response;
}
private void logRequestDetails(HttpRequest request, byte[] body) {
log.debug("Headers: {}", request.getHeaders());
log.debug("body: {}", new String(body, Charsets.UTF_8));
log.debug("{}:{}", request.getMethod(), request.getURI());
}
private void logResponseDetails(ClientHttpResponse response) throws IOException
{
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()));
}
}
三、自定义配置RestTemplate
一般不用这种方式,其实Spring默认配置的已经很好用了
添加HttpClient依赖
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>x.x.x</version> <!-- springboot项目不用指定 -->
</dependency>
配置
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.customizers(restTemplateCustomizer())
.additionalInterceptors(new CustomClientHttpRequestInterceptor())
.errorHandler(xxxxx) //定义错误处理器
.build();
}
/**
* 定制化RestTemplate
* @return
*/
@Bean
public RestTemplateCustomizer restTemplateCustomizer(){
return restTemplate -> {
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
//创建连接管理器 默认就支持https http
PoolingHttpClientConnectionManager pM = new PoolingHttpClientConnectionManager();
//最大连接数
pM.setMaxTotal(100);
//同路由并发数
pM.setDefaultMaxPerRoute(20);
httpClientBuilder.setConnectionManager(pM);
//创建httpClient
HttpClient httpClient = httpClientBuilder.build();
//创建HttpComponentsClientHttpRequestFactory
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
//连接超时
requestFactory.setConnectTimeout(10 * 1000);
//数据读取超时时间
requestFactory.setReadTimeout(60 * 1000);
//连接不够用的等待时间
requestFactory.setConnectionRequestTimeout(30 * 1000);
//设置请求工厂
restTemplate.setRequestFactory(requestFactory);
//用UTF-8 StringHttpMessageConverter替换默认StringHttpMessageConverter
//可以解决请求回来的数据乱码问题
List<HttpMessageConverter<?>> newMessageConverters = new ArrayList<>();
for(HttpMessageConverter<?> converter : restTemplate.getMessageConverters()){
if(converter instanceof StringHttpMessageConverter){
StringHttpMessageConverter messageConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
newMessageConverters.add(messageConverter);
}else {
newMessageConverters.add(converter);
}
}
restTemplate.setMessageConverters(newMessageConverters);
};
}
四、RestTemplate API使用
postForEntity()(有请求体)
//设置请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.add("key1","value1");
headers.add("key2","value2");
HttpEntity<User> entity = new HttpEntity<>(new User(), headers);
String url = "http://xxx.com";
//发送post请求
ResponseEntity<R> responseEntity = restTemplate.postForEntity(url, entity, R.class);
R r = responseEntity.getBody();
if (HttpStatus.OK.value() != r.getStatus()) {
log.error("发送错误:{}", r.getMsg());
}
postForEntity()(有请求参数)
String url="http://xxx.com??p1={1}&p2={2}";
ResponseEntity<Map> responseEntity = restTemplate.postForEntity(
url,
null,
Map.class,
"aa","bb");
postForObject()
//参数是Book类型,返回值也是Book类型
Book book = restTemplate.postForObject("http://127.0.0.1:8080/updatebook", book, Book.class);
post方法获取List数据
List<ProductTypeVO> voList = Lists.newArrayList();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
headers.add("key1","value1");
headers.add("key2","value2");
HttpEntity<String> entity = new HttpEntity<>("", headers);
ProductTypeVO[] responseEntity = restTemplate.postForObject(
url,
entity,
ProductTypeVO[].class);
if (null != responseEntity) {
voList = Arrays.asList(responseEntity);
}
作者:缓慢移动的蜗牛
链接:https://www.jianshu.com/p/35aca2e31f06
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。