spring之resttemplate常用api实践(代码片段)

一宿君 一宿君     2023-03-21     745

关键词:

目录


1、RestTemplate简介

在开发的过程中,很多时候我们需要从当前服务端(当前项目)向外进行网络请求(其他项目)获取数据或传送数据,传统情况下,我们一般会使用JDK自带的HttpURLConnectionApache提供的HttpClientOkHttp等客户端请求工具,但是这几种方式使用起来比较繁琐,对于初学者来说不太友好,而Spring为我们提供了一个快捷方便的Restful模板类请求工具类RestTemplate

RestTemplate是一个执行HTTP请求的同步阻塞式请求工具类,它是在JDK HttpURLConnectionApache HttpComponentsOkHttp等客户端的基础上,封装了更高级别的API,使在单行中调用REST端点变得容易。RestTemplate默认是依赖JDK HttpURLConnection,可以根据实际需要通过构造函数中的setRequestFactory方法设置底层依赖请求客户端。

public RestTemplate(ClientHttpRequestFactory requestFactory) 
      this();
      this.setRequestFactory(requestFactory);//指定HTTP客户端

2、RestTemplate初始化配置

如果当前是SpringBoot项目(非spring环境),我们需要导入Spring-web依赖,即可引入RestTemplate类:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>5.2.0.RELEASE</version>
</dependency>

如果当前是SpringBoot项目(spring环境),我们只需要导入spring-boot-starter-web依赖,即可引入RestTemplate类:

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

内置支持以下功能:

  • JDK HttpURLConnection
  • Apache HttpComponents
  • OkHttp

RestTemplate包含以下几个部分:

  • HttpMessageConverter对象转换器
  • ClientHttpRequestFactory 默认是JDKHttpURLConnection
  • ResponseErrorHandler 异常处理器
  • ClientHttpRequestInterceptor 请求拦截器

我们现在大多使用SpringBoot框架,为了后续方便使用,我们将RestTemplate配置初始化为一个Bean

@Configuration
public class RestTemplateConfig 

    @Bean
    @ConditionalOnMissingBean(RestTemplate.class)
    public RestTemplate restTemplate()
        RestTemplate restTemplate = new RestTemplate(getSimpleClientHttpRequestFactory());
        return restTemplate;
    
    
    /**
     * 默认底层依赖JDK HttpURLConnection作为HTTP客户端
     * @return
     */
    public ClientHttpRequestFactory getSimpleClientHttpRequestFactory() 
        int timeout = 5000;
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setReadTimeout(timeout);
        factory.setConnectTimeout(timeout);
        return factory;
    

在项目启动的时候会默认加载当前配置类中的@Bean注解方法,将restTemplate()方法注入Spring容器中,注意: @Bean注解的方法名最好是restTemplate首字母小写,后续我们在需要用到的地方直接@Autowire自动装载即可使用。

@Autowired
private RestTemplate restTemplate;

通过管方指导文档描述:

The default constructor uses java.net.HttpURLConnection to perform requests. You can switch to a different HTTP library with an implementation of ClientHttpRequestFactory. There is built-in support for the following:
释义:默认构造函数使用java.net.HttpURLConnection执行请求。您可以切换到具有`ClientHttpRequestFactory`实现的不同HTTP库。
    
//直接new RestTemplate();底层依赖的也是JDK HttpURLConnection

如果我们想切换到Apache HttpComponents客户端,可以使用以下方式:

首先导入Apache HttpClient依赖:

<!-- Apache Httpclient -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.6</version>
</dependency>

初始化:

RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

但是通常情况下,我们切换客户端会预先做一些连接请求超时参数配置,如下:

@Configuration
public class RestTemplateConfig 

    /**
     * 使用Apache HttpClient作为底层客户端
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(RestTemplate.class)
    public RestTemplate restTemplate()
		//RestTemplate restTemplate = new RestTemplate();
        RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
        return restTemplate;
    


    /**
     * 使用Apache HttpClient作为底层客户端
     * @return
     */
    private ClientHttpRequestFactory getClientHttpRequestFactory()
        int timeout = 5000;
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(timeout)
                .setConnectTimeout(timeout)
                .setSocketTimeout(timeout)
                .build();
        CloseableHttpClient client = HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .build();
        return new HttpComponentsClientHttpRequestFactory(client);
    

切换为OkHttp客户端:

先导入依赖:

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

初始化:

RestTemplate template = new RestTemplate(new OkHttp3ClientHttpRequestFactory());

预先做一些连接请求超时参数配置,如下:

@Configuration
public class RestTemplateConfig 

    /**
     * 使用OkHTTP作为底层客户端
     * @return
     */
    @Bean
    @ConditionalOnMissingBean(RestTemplate.class)
    public RestTemplate restTemplate()
		//RestTemplate restTemplate = new RestTemplate();
		//RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
        RestTemplate restTemplate = new RestTemplate(getOkHttp3ClientHttpRequestFactory());
        return restTemplate;
    

    /**
     * 使用OkHTTP作为底层客户端
     * @return
     */
    private OkHttp3ClientHttpRequestFactory getOkHttp3ClientHttpRequestFactory()
        int timeout = 5000;
        OkHttpClient okHttpClient = new OkHttpClient();
        OkHttp3ClientHttpRequestFactory okHttp3ClientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory(okHttpClient)
            setConnectTimeout(timeout);
            setReadTimeout(timeout);
            setWriteTimeout(timeout);
        ;
        return okHttp3ClientHttpRequestFactory;
    

具网上不完全统计,上述Http客户端的效率:

OkHttp > Apache HttpClient > JDK HttpURLConnection

所以下述我们以OkHttp作为底层客户端依赖。

扩展:

@ConditionalOnMissingBean(RestTemplate.class)

当注入多个相同类型的Bean时,会报异常,此注解就是保证当前类型Bean只能有一个实例化对象。

@ConditionalOnBean // 当给定的在bean存在时,则实例化当前Bean

@ConditionalOnMissingBean // 当给定的在bean不存在时,则实例化当前Bean

@ConditionalOnClass // 当给定的类名在类路径上存在,则实例化当前Bean

@ConditionalOnMissingClass // 当给定的类名在类路径上不存在,则实例化当前Bean

3、RestTemplate常用API实践

Spring之RestTemplate官方指导文档。

它公开了以下几组重载方法:

方法描述
getForObject通过GET检索一个表示。
getForEntity通过使用GET检索一个ResponseEntity(即状态、标题和主体)。
headForHeaders通过使用HEAD检索资源的所有标头。
postForLocation使用POST创建一个新资源,并从响应中返回Location报头。
postForObject使用POST创建新资源,并从响应返回表示。
postForEntity使用POST创建新资源,并从响应返回表示。
put通过使用PUT创建或更新资源。
patchForObject使用PATCH更新资源,并从响应返回表示。注意,JDK HttpURLConnection 不支持PATCH,但Apache HttpComponents和其他组件支持。
delete使用DELETE删除指定URI处的资源。
optionsForAllow使用ALLOW为资源检索允许的HTTP方法。
exchange在需要时提供额外灵活性的前面方法的更一般化(且不那么自以为是)版本。它接受一个’RequestEntity (包括HTTP方法、URL、报头和主体作为输入),并返回一个ResponseEntity。这些方法允许使用ParameterizedTypeReference代替Class来指定具有泛型的响应类型。
execute执行请求的最通用方法,通过回调接口完全控制请求准备和响应提取。

将上述方法大致归为三类:

常用的Rest API(GET、POST、PUT、DELETE):

  • getForObject
  • getForEntity
  • headForHeaders
  • postForLocation
  • postForObject
  • postForEntity
  • put
  • patchForObject
  • delete
  • optionsForAllow

接收一个 RequestEntity 参数,自定义设置HTTP methodURLheadersbody,返回 ResponseEntity:

  • exchange

通过 callback 接口,可以对请求和返回做更加全面的自定义控制:

  • execute

创建一个响应实体类ResponseBean

@Data
@ToString
public class ResponseBean<T> 
    /**
     * 状态码 200 成功 其他失败
     */
    private String code;

    /**
     * 响应数据
     */
    private T data;

    /**
     * 异常信息
     */
    private String message;

创建一个请求实体类RequestBean

@Data
public class RequestBean 
    /**
     * 用户id
     */
    private String userCode;

    /**
     * 
     */
    private String userName;

3.1、GET类型方法

通过RestTemplate发送HTTP GET协议请求,经常会用到以下两个方法:

  • getForObject():返回值是HTTP协议的响应体内容
  • getForEntity():返回的是ResponseEntityResponseEntity是对HTTP响应的封装,除了包含响应体,还包含HTTP状态码、contentType、contentLength、Header等信息

getForObject()重载方法:

@Nullable
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException 

@Nullable
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException 

@Nullable
public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException 

getForEntity()重载方法:

public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException 

public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException 

public <T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException 

3.1.1、GET无参请求方法之getForObject()

创建一个无参get请求接口:

@RestController
@RequestMapping("/rest")
public class RestTemplateController 

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/no/param/test/get")
    public ResponseBean<String> testGet1()
        ResponseBean<String> responseBean = new ResponseBean<String>();
        responseBean.setCode("200");
        responseBean.setData("无参get请求!");
        responseBean.setMessage(null);
        return responseBean;
    

单元测试无参get请求:

@SpringBootTest
@RunWith(SpringRunner.class)
public class RestTemplateTest 

    @Autowired
    private RestTemplate restTemplate;

    @Test
    public void testGet1()
        String url = "http://localhost:6625/rest/no/param/test/get";
        ResponseBean response = restTemplate.getForObject(url, ResponseBean.class);
        System.out.println(response);
    

打印结果:

"code":"200","data":"响应成功了!","message":null

发现出现了乱码,原因在于RestTemplate中对字符串默认使用的转换器是StringHttpMessageConverter,而StringHttpMessageConverter默认的字符集编码是ISO_8859_1:

public class StringHttpMessageConverter extends AbstractHttpMessageConverter<String> 
    public static final Charset DEFAULT_CHARSET;

    public StringHttpMessageConverter() 
        this(DEFAULT_CHARSET);
      
    
    static 
        //默认字符集
        DEFAULT_CHARSET = StandardCharsets.ISO_8859_1;
    

ISO_8859_1编码格下,中文是乱码的。因此我们需要将编码格式设置为UTF-8的格式才能支持中文:

@Configuration
public class RestTemplateConfig 


    @Bean
    @ConditionalOnMissingBean(RestTemplate.class)
    public RestTemplate restTemplate()
        RestTemplate restTemplate = new RestTemplate(getOkHttp3ClientHttpRequestFactory());
        //设置RestTemplate的字符集为UTF-8
        setRestTemplateEncode(restTemplate);
        return restTemplate;
    

    /**
     * 使用OkHTTP作为底层客户端
     * @return
     */
    private OkHttp3ClientHttpRequestFactory getOkHttp3ClientHttpRequestFactory()
        int timeout = 5000;
        OkHttpClient okHttpClient = new OkHttpClient();
        OkHttp3ClientHttpRequestFactory okHttp3ClientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory(okHttpClient)
            setConnectTimeout(timeout);
            setReadTimeout(timeout);
            setWriteTimeout(timeout);
        ;
        return okHttp3ClientHttpRequestFactory;
    

    /**
     * 指定设置RestTemplate的字符转换器编码为UTF_8
     * @param restTemplate
     */
    public static void setRestTemplateEncode(RestTemplate restTemplate) 
        if (ObjectUtils.isEmpty(restTemplate) || ObjectUtils.isEmpty(restTemplate.getMessageConverters()))
            return;
        
        List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
        for (int i = 0; i < messageConverters.size(); i++) 
            HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
            if (StringHttpMessageConverter.class.equals(httpMessageConverter.getClass()))
                messageConverters.set(i,new StringHttpMessageConverter(StandardCharsets.UTF_8));
            
        
    

再次重启,打印结果:

ResponseBean(code=200, data=无参get请求!, message=null)

问题解决!

3.1.2、GET占位符传参请求方法之getForObject()

创建一个占位符传参get请求接口:

@RestController
@RequestMapping("/rest")
public class RestTemplateController 

    @Autowired
    private RestTemplate restTemplate;
    
    @GetMapping("/path/param/test/get/code/data")
    public ResponseBean<String> testGet2(@PathVariable("code") String code,@PathVariable("data") String data)
        ResponseBean<String> responseBean = new ResponseBean<String>();
        responseBean.setCode(code);
        responseBean.setData(data);
        responseBean.setMessage(null);
        return responseBean;
    

单元测试占位符传参get请求:

@SpringBootTest
@RunWith(SpringRunner.class)
public class RestTemplateTest 

    @Autowired
    private RestTemplate restTemplate;

    @Test
    public void testGet2()
        String url = "http://localhost:6625/rest/path/param/test/get/code/data";
        ResponseBean response = restTemplate.getForObject(url, ResponseBean.class,"200","占位符传参get请求&

javaspring之resttemplate的使用

RestTemplate介绍  调用远程服务时就必须使用HTTP客户端,主要有四种:JDK原生的URLConnection、Apache的HttpClient、Netty的异步HTTPClient,Spring的RestTemplate。    解放了原先HttpClient的复杂提交,java中调用RESTful服务很典型的是使用HttpCli... 查看详情

小白一看就会的spring的resttemplate的使用

写在前面您好,我是码农飞哥,感谢您阅读此文。作为一名Java开发者,我们怎么都绕不开调用外部接口的场景,调用的方式要么是通过Http协议来调用,要么是通过RPC协议来调用,通过Http协议调用的话我们就需要用到Http的Api。... 查看详情

使用 spring restTemplate 对 REST API 进行基本身份验证

】使用springrestTemplate对RESTAPI进行基本身份验证【英文标题】:BasicauthenticationforRESTAPIusingspringrestTemplate【发布时间】:2014-03-2203:09:35【问题描述】:我是RestTemplate的新手,基本上也是RESTAPI的新手。我想通过JiraRESTAPI在我的应用程... 查看详情

spring的resttemplate

Spring提供了一个RestTemplate模板工具类,对基于Http的客户端进行了封装,并且实现了对象与json的序列化和反序列化,非常方便。RestTemplate并没有限定Http的客户端类型,而是进行了抽象,目前常用的3种都有支持:-HttpClient-OkHttp-JDK... 查看详情

Spring RestTemplate 配置策略从单个 API 调用多个休息服务

】SpringRestTemplate配置策略从单个API调用多个休息服务【英文标题】:SpringRestTemplateconfigurationstrategiestocallmultiplerestservicesfromasingleAPI【发布时间】:2018-08-1500:31:15【问题描述】:我有一个场景,其中有一个聚合端点来调用多个下游... 查看详情

无法在 Spring Boot 中通过 RestTemplate 和 Eureka 使用 REST API

】无法在SpringBoot中通过RestTemplate和Eureka使用RESTAPI【英文标题】:NotabletoconsumeaRESTAPIthroughRestTemplateandEurekainSpringBoot【发布时间】:2018-05-0821:37:53【问题描述】:我可以在我的SpringBoot应用程序中通过Feign使用RESTAPI,但不能通过RestT... 查看详情

resttemplate|使用详解(代码片段)

...端调用接口的方式有很多,这里介绍基于Spring框架的RestTemplate。文章目录RestTemplate的使用getForObject的使用getForEntity的使用postForObject的使用postForEntity的使用exchange的使用常见的HTTP客户端请求工具:JDKHttpURLConnectionhttpclientOkH... 查看详情

RestTemplate、Spring 启动、POST

】RestTemplate、Spring启动、POST【英文标题】:RestTemplate,Springboot,POST【发布时间】:2018-12-1511:04:42【问题描述】:我在localhost:8086/addMessage有一个restapi,当我使用POSTMAN测试它时它可以工作。但是当我想在客户端集成这个api时,它会... 查看详情

Spring/RestTemplate - PUT 实体到服务器

】Spring/RestTemplate-PUT实体到服务器【英文标题】:Spring/RestTemplate-PUTentitytoserver【发布时间】:2016-01-1910:27:30【问题描述】:请看这个简单的代码:finalStringurl=String.format("%s/api/shop",Global.webserviceUrl);RestTemplaterestTemplate=newRestTemplat 查看详情

springboot系列之resttemplate使用示例(代码片段)

...写一些http请求比较麻烦,学习springboot的过程知道可以用RestTemplate来做http请求,RestTemplate是SpringFramework框架封装的基于模板方法设计模式的一个工具类,带有同步模板方法API的原始SpringREST客户端类,下面博主分析一些对接过程... 查看详情

resttemplate使用(代码片段)

RestTemplate介绍RestTemplate简介? spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接,我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,Rest... 查看详情

springboot系列之resttemplate使用示例

...些http请求比较麻烦,学习springboot的过程知道可以用RestTemplate来做http请求,RestTemplate是SpringFramework框架封装的基于模板方法设计模式的一个工具类,带有同步模板方法API的原始SpringREST客户端类,下面博主分析一些... 查看详情

resttemplate使用教程(代码片段)

一、概述spring框架提供的RestTemplate类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统一了RESTful的标准,封装了http链接,我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient,RestTemplate是一种更优雅... 查看详情

使用注入 java 和 spring boot 的 RestTemplate 类进行单元测试

】使用注入java和springboot的RestTemplate类进行单元测试【英文标题】:UnittestusingclasswithRestTemplateinjectedwithjavaandspringboot【发布时间】:2019-11-2110:40:29【问题描述】:我正在使用注入了RestTemplate的类运行单元测试,并且只有在我运行... 查看详情

spring5之webclient简单使用

参考技术ASpring3.0引入了RestTemplate,但是在后来的官方源码中介绍,RestTemplate有可能在未来的版本中被弃用,所谓替代RestTemplate,在Spring5中引入了WebClient作为非阻塞式ReactiveHttp客户端。采用阻塞IO模式获取输入数据。每个连接都... 查看详情

springresttemplate之get请求

一,简介:SpringRestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率二、RestTemplate中几种常见请求方法的使用    ●get请求:在RestTem... 查看详情

使用 Spring RestTemplate for Android 发出经过身份验证的 POST 请求

】使用SpringRestTemplateforAndroid发出经过身份验证的POST请求【英文标题】:MakingauthenticatedPOSTrequestswithSpringRestTemplateforAndroid【发布时间】:2012-05-0815:46:07【问题描述】:我有一个RESTfulAPI,我正在尝试通过Android和RestTemplate进行连接... 查看详情

在 Spring Boot 中通过 RestTemplate POST JSON 对象

】在SpringBoot中通过RestTemplatePOSTJSON对象【英文标题】:POSTJSONObjectviaRestTemplateinSpringBoot【发布时间】:2019-06-2009:22:33【问题描述】:我正在尝试将JSON对象发布到接受以下格式数据的API端点"names":["name1","name2","name3"]我的post方法如... 查看详情