所有分类
  • 所有分类
  • 未分类

Spring之HTTP客户端–RestTemplate的使用

简介

本文介绍RestTemplate的用法。RestTemplate是Spring自带的HTTP客户端,推荐使用。

项目中经常需要使用http调用第三方的服务,常用的客户端如下:

  1. HttpURLConnection(JDK的)
  2. HttpClient(Apache的)
  3. OkHttp(Square的)

上边这几个客户端用起来比较麻烦,代码量比较多,而且要注意资源回收问题。Spring提供了一个简单便捷的工具类,它就是RestTemplate。RestTemplate的底层默认是HttpURLConnection(JDK),可以切换为其他客户端,比如:HttpClient(Apache的)、OkHttp(Square的)。

引入依赖

只需引入spring-boot-starter-web即可,它里边包含了RestTemplate。

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

配置类

法1:最简配置

@Configuration
public class RestTemplateConfig {
	@Bean
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}
}

这种初始化方法,是使用了JDK自带的HttpURLConnection作为底层HTTP客户端实现。 

法2:自定义客户端及超时等

建议自定义配置,原因如下:

  1. 从性能及易用程度来看,OkHttp 优于 HttpClient、HttpClient优于HttpURLConnection。
  2. 超期时间,请求连接时间等是HTTP客户端必须要设置的,要支持配置。

RestTemplate工具提供两种配置方式。

  1. RestTemplate类
    1. 优点:可以便捷创建一些错误处理拦截、添加默认请求参数等。
  2. RestTemplateBuilder
    1. 优点:可以便捷设置连接超时和读超时
    2. Spring已默认将RestTemplateBuilder装配为了Bean,直接使用即可。
package com.knife.example.common.config;

import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;

@Configuration
public class RestTemplateConfig {
    @Value("${custom.restTemplate.connectTimeout:1s}")
    private Duration connectTimeout;

    @Value("${custom.restTemplate.readTimeout:1s}")
    private Duration readTimeout;

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder){
        RestTemplate restTemplate = restTemplateBuilder
                .requestFactory(this::getClientHttpRequestFactory)
                .setConnectTimeout(connectTimeout)
                .setReadTimeout(readTimeout)
                // 响应异常处理。应用场景:响应状态200是正常,可以做统一的非200响应码的拦截
                // .errorHandler(ResponseErrorHandler errorHandler)
                // 设置请求拦截。应用场景:添加一些全局的请求头等。可创建多个,执行顺序和list中对象的顺序一致。
                // .interceptors(List<ClientHttpRequestInterceptor> interceptors)
                // 设置信息转换对象。应用场景:设置一些编码格式、数据类型、json/xml等的类型转换器等。
                // .messageConverters(List<HttpMessageConverter<?>> messageConverters)
                // 配置一个扩展uri模板的策略。应用场景:添加一些统一的请求前缀等。
                // .uriTemplateHandler(UriTemplateHandler handler)
                .build();

        return restTemplate;
    }

    /**
     * 使用OkHttpClient作为底层客户端(要引入okhttp依赖:com.squareup.okhttp3:okhttp:xxx)
     */
    private ClientHttpRequestFactory getClientHttpRequestFactory(){
        // 这里设置超时时间是无效的,以外边的restTemplateBuilder.setXxxTimeout为准
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                // .connectTimeout(5, TimeUnit.SECONDS)
                // .readTimeout(5, TimeUnit.SECONDS)
                // .writeTimeout(5, TimeUnit.SECONDS)
                .build();
        return new OkHttp3ClientHttpRequestFactory(okHttpClient);
    }

    // /**
    //  * 使用HttpClient作为底层客户端(要引入httpclient依赖:org.apache.httpcomponents:httpclient:xxx)
    //  */
    // private ClientHttpRequestFactory getClientHttpRequestFactory() {
    //     //这里设置超时时间是无效的,以外边的restTemplateBuilder.setXxxTimeout为准
    //     RequestConfig config = RequestConfig.custom()
    //             // 单位都是:毫秒
    //             .setConnectTimeout(2000)
    //             .setConnectionRequestTimeout(1000)
    //             .setSocketTimeout(1000)
    //             .build();
    //     CloseableHttpClient client = HttpClientBuilder
    //             .create()
    //             .setDefaultRequestConfig(config)
    //             .build();
    //
    //     return new HttpComponentsClientHttpRequestFactory(client);
    // }

}

使用

注入RestTemplate即可。

例1:基础用法

package com.knife.controller;

import com.knife.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class HelloController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("testGetForObject")
    public User testGetForObject(String id) {
        User user = restTemplate.getForObject("http://localhost/get/{id}", User.class, id);
        System.out.println(user);
        
        return user;
    }

    @GetMapping("testGetForEntity")
    public User getForEntity(String id) {
        ResponseEntity<User> userResponseEntity = restTemplate.getForEntity(
                "http://localhost/get/{id}", User.class, id);
        User user = userResponseEntity.getBody();
        System.out.println(user);
        
        return user;
    }
}

例2:自定义Header、请求方法等

package com.knife.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@RestController
public class HelloController {

    @Autowired
    private RestTemplate restTemplate;
    
    @PostMapping("testExecute")
    public void testExecute(Integer id, String name) {

        HttpHeaders headers = new HttpHeaders();
        headers.add("authorization", "aaabbb");
        headers.setContentType(MediaType.APPLICATION_JSON);

        Map<String, Object> body = new HashMap<>();
        body.put("userId", id);
        body.put("name", name);

        HttpEntity<Map> httpEntity = new HttpEntity<>(body, headers); // 组装

        ResponseEntity<User> user = restTemplate.exchange(
               "http://localhost:8080/demo", HttpMethod.POST, httpEntity, User.class);
    }
}

用法大全

  1. delete()
    1. 在特定的URL上对资源执行HTTP DELETE操作
  2. exchange()
    1. 通用的方法。在URL上执行特定的HTTP方法,返回包含对象的ResponseEntity,这个对象是从响应体中映射得到的。
  3. execute()
    1. 在URL上执行特定的HTTP方法,返回一个从响应体映射得到的对象。这是个偏底层的方法,其他方法是基于此方法的,不建议用户直接使用。
  4. getForEntity()
    1. 发送一个HTTP GET请求,返回的ResponseEntity包含了响应体所映射成的对象
  5. getForObject()
    1. 发送一个HTTP GET请求,返回的响应体将映射为一个对象
  6. postForEntity()
    1. 发送一个HTTP POST请求,返回包含一个对象的ResponseEntity,这个对象是从响应体中映射得到的
  7. postForObject()
    1. 发送一个HTTP POST请求,返回根据响应体匹配形成的对象
  8. headForHeaders()
    1. 发送HTTP HEAD请求,返回包含特定资源URL的HTTP头
  9. optionsForAllow()
    1. 发送HTTP OPTIONS请求,返回对特定URL的Allow头信息
  10. postForLocation()
    1. 发送HTTP POST请求,返回新创建资源的URL
  11. put()
    1. 发送HTTP PUT请求

0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录