RestTemplate请求模板详解

什么是RestTemplate

RestTemplate是从Spring 3.0开始支执行Http请求的客户端工具,常见的Http客户端库有

  • Java JDK自带的HttpURLConnection

  • Apache HttpComponents

  • OkHttp

这些客户端库对,提供常见的REST请求模板,例如Get、Post、PUT和Delete请求,相对于直接使用底层Http客户端库,RestTemplate的操作更加方便、快捷在很大程度上提高开发效率。

HttpClient、OkHttp、RestTemplate对比:

  • HttpClient:代码复杂,还得操心资源回收等。代码很复杂,冗余代码多,不建议直接使用,一般是封装为 HttpUtils工具类使用。

  • RestTemplate: 是 Spring 提供的用于访问Rest服务的客户端, RestTemplate 提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

  • okhttp:OkHttp是一个高效的HTTP客户端,允许所有同一个主机地址的请求共享同一个socket连接;连接池减少请求延时;透明的GZIP压缩减少响应数据的大小;缓存响应内容,避免一些完全重复的请求

SpringBoot引入RestTemplate

从Spring3.0引入RestTemplate后它就作为spring-web的一部分,而spring-boot-starter-web保重包含了spring-web

因此只需要添加spring-boot-starter-web依赖即可

<dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
</dependency>

RestTemplate初始化

SpringBoot在AutoConfig的时候,自动注入了JDK自带的HttpURLConnection作为RestTemplate底层的Http客户端实现,也可以将底层的Http实现转换为OkHttp,Apache HttpComponents,并且需要初始化Bean。所以RestTemplate是支持多种方式发起请求的,查看该工程的实现类可知,支持包括HttpClient, OkHttp等方式。

@Configuration
public class MyRestTemplate {

    /**
     * 默认使用JDK 自带的HttpURLConnection作为底层实现
     * @return
     */
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

底层Http客户端库切换

我们在网上对Http客户端的测评来看OkHttp的性能优于Apache HttpComponents和JDK自带的HttpURLConnection,那么我们如何将底层Http客户端库切换为我们需要使用的Http客户端库呢?

切换为OkHttp

添加依赖

        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.1</version>
        </dependency>

初始化RestTemplate的Bean

 @Bean
    public RestTemplate restTemplateOkHttp(){
        return  new RestTemplate(new OkHttp3ClientHttpRequestFactory());
    }

切换为Apache HttpComponents

添加依赖

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.13</version>
        </dependency>

初始化RestTemplate的Bean

    @Bean
    public  RestTemplate restTemplateHttpClient(){
        return new RestTemplate(new HttpComponentsClientHttpRequestFactory());
    }

RestTemplate的使用

基础原理

RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。RestTemplate 继承自 InterceptingHttpAccessor 并且实现了 RestOperations 接口,其中 RestOperations 接口定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现。

RestTemplate restTemplate = new RestTemplate();
RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory());

RestTemplate提供了六种常用的HTTP方法实现远程服务调用,RestTemplate的方法名遵循一定的命名规范,第一部分表示用哪种HTTP方法调用(get,post),第二部分表示返回类型。

getForObject – 发送GET请求,将HTTP response转换成一个指定的object对象

postForEntity –发送POST请求,将给定的对象封装到HTTP请求体,返回类型是一个HttpEntity对象(包含响应数据和响应头)

每个HTTP方法对应的RestTemplate方法都有3种。其中2种的url参数为字符串,URI参数变量分别是Object数组和Map,第3种使用URI类型作为参数

exchange 和execute方法比上面列出的其它方法(如getForObject、postForEntity等)使用范围更广,允许调用者指定HTTP请求的方法(GET、POST、PUT等),并且可以支持像HTTP PATCH(部分更新)。

发送请求不携带数据

1、发起get请求请求

发送一个HTTP GET请求,返回的请求体将映射为一个对象

getForObject()

发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象

getForEntity()
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> entity = restTemplate.getForEntity(uri, String.class);
// TODO 处理响应

2、发起Post请求方式

POST 数据到一个URL,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的。

postForEntity()

POST 数据到一个URL,返回根据响应体匹配形成的对象。

postForObject()

POST 数据到一个URL,返回新创建资源的URL

postForLocation()
RestTemplate restTemplate = new RestTemplate();
// headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<Object> objectHttpEntity = new HttpEntity<>(headers);
// TODO 处理响应
ResponseEntity<String> entity = restTemplate.postForEntity(uri, request, String.class);

发送请求携带请求数据

方式一:在每次发送请求时,构建一个HttpEntity对象,传入请求参数与请求头

使用 RestTemplate 时可以通过 HttpEntity 设置请求头和请求体。HttpEntity 有4个构造方法:

  1. 既不设置请求体,也不设置请求头

  1. 只设置请求体

  1. 只设置请求头

  1. 同时设置请求体和请求头

@GetMapping("/test")
public Map<String, Object> getBlobMetadataList(){
    // 构建你的请求头
    HttpHeaders headers = new HttpHeaders();
    headers.set("xxx","xxx");
    headers.set("Content-Type", "application/json");
    // 构建你的请求体参数
    HashMap<String, String> map = new HashMap<>();
    map.put("yourParma", "youValue");
    // 组合请求头与请求体参数
    HttpEntity<String> requestEntity = new HttpEntity<>(JSONObject.toJSONString(map), headers);
    // path -> 请求地址,requestEntity -> 请求参数相关对象,HashMap.class -> 返回结果映射类型
    return restTemplate.postForObject(path, requestEntity, HashMap.class);
}

方式二:通过配置RestTemplate,使通过RestTemplate调用的http请求都携带上请求头

对于一些共同的请求头,如果在每一次发送请求调用时都去重头构建一个HttpEntity请求头,在代码上重复不说,看着也不舒服,以下为配置统一的请求头,让每次请求都自动携带上请求头,一劳永逸!

同时设置请求头和请求体:

/**
 * RestTemplate配置类
 */
@Slf4j
@Configuration
public class RestTemplateConfig {
 
    /**
     * 常用远程调用RestTemplate
     * @return restTemplate
     */
    @Bean("restTemplate")
    public RestTemplate restTemplate(){
        RestTemplate restTemplate = new RestTemplate();
        // 设置通用的请求头
        //HeaderRequestInterceptor myHeader = new HeaderRequestInterceptor("xxx","xxx");              
        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
        interceptors.add(new HeaderRequestInterceptor("Content-type", "application/json;charset=UTF-8"));
        restTemplate.setInterceptors(interceptors);
        return restTemplate;
    }
 
   /**
     * 拦截器类,为restTemplatep后续调用请求时携带请求头
     */
    public static class HeaderRequestInterceptor implements ClientHttpRequestInterceptor{
 
        private final String header;
 
        private final String value;
 
        public HeaderRequestInterceptor(String header, String value){
            this.header = header;
            this.value = value;
        }
 
        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
            request.getHeaders().set(header, value);
            return execution.execute(request, body);
        }
    }
}

为其他请求设置请求头、请求体

如果是其它HTTP方法调用要设置请求头,可以使用exchange()方法:

HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.set("MyRequestHeader", "MyValue");
HttpEntity requestEntity = new HttpEntity(requestHeaders);
HttpEntity<String> response = template.exchange(
        "http://example.com/hotels/{hotel}",
        HttpMethod.GET, 
        requestEntity, 
        String.class, 
        "42"
    );
String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
String body = response.getBody();
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值