2020-12-03

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远程请求接口的理解和用法,希望可以帮到大家,写这些东西,只是为了更好的记住这些用法,不喜勿喷,有什么建议欢迎留言,多总结,多修改,才能成长,小白一枚,还望大佬多多指教

上一篇:springcloud入门resttemplate&eureka&ribbon&hystrix


下一篇:Spring应用消费REST服务