跳至主要內容

RestTemplate 教程

悟空约 989 字大约 3 分钟...

原文链接:https://www.jianshu.com/p/35aca2e31f06open in new window

一、概述

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/35aca2e31f06open in new window
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v3.3.0