RestTemplate使用教程

一、概述 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依赖
org.apache.httpcomponents httpclient x.x.x

配置
@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> 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 entity = new HttpEntity<>(new User(), headers); String url = "http://xxx.com"; //发送post请求 ResponseEntity 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 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 voList = Lists.newArrayList(); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON_UTF8); headers.add("key1","value1"); headers.add("key2","value2"); HttpEntity entity = new HttpEntity<>("", headers); ProductTypeVO[] responseEntity = restTemplate.postForObject( url, entity, ProductTypeVO[].class); if (null != responseEntity) { voList = Arrays.asList(responseEntity); }

五、其他参考文章 【RestTemplate使用教程】https://www.baeldung.com/rest-template
https://www.jianshu.com/p/0fd5f3f64137
https://www.xncoding.com/2017/07/06/spring/sb-restclient.html

    推荐阅读