restTemplate配置及使用过程

 更新时间:2025年11月10日 09:14:49   作者:水煮鱼又失败了  
本文介绍了在Java开发中使用HttpClient和OKHttp进行HTTP连接的复杂性,推荐使用Spring框架的RestTemplate进行简化,RestTemplate支持多种HTTP连接方式,并提供了丰富的API进行GET、POST请求和文件上传,文章还提供了具体的代码示例

1 场景

java开发中,使用http连接,访问第三方网络接口,通常使用的连接工具为HttpClientOKHttp

这两种连接工具,使用起来比较复杂,新手容易出问题。如果使用spring框架,可以使用restTemplate来进行http连接请求。

restTemplate默认的连接方式是java中的HttpConnection,可以使用ClientHttpRequestFactory指定不同的HTTP连接方式。

2 依赖

maven依赖如下:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.7</version>
</dependency>

3 配置

import org.apache.http.client.HttpClient;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
    
    /**
     * http连接管理器
     * @return
     */
    @Bean
    public HttpClientConnectionManager poolingHttpClientConnectionManager() {
        /*// 注册http和https请求
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);*/
        
        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
        // 最大连接数
        poolingHttpClientConnectionManager.setMaxTotal(500);
        // 同路由并发数(每个主机的并发)
        poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100);
        return poolingHttpClientConnectionManager;
    }
    
    /**
     * HttpClient
     * @param poolingHttpClientConnectionManager
     * @return
     */
    @Bean
    public HttpClient httpClient(HttpClientConnectionManager poolingHttpClientConnectionManager) {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        // 设置http连接管理器
        httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
        
        /*// 设置重试次数
        httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));*/
        
        // 设置默认请求头
        /*List<Header> headers = new ArrayList<>();
        headers.add(new BasicHeader("Connection", "Keep-Alive"));
        httpClientBuilder.setDefaultHeaders(headers);*/
        
        return httpClientBuilder.build();
    }
    
    /**
     * 请求连接池配置
     * @param httpClient
     * @return
     */
    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory(HttpClient httpClient) {
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        // httpClient创建器
        clientHttpRequestFactory.setHttpClient(httpClient);
        // 连接超时时间/毫秒(连接上服务器(握手成功)的时间,超出抛出connect timeout)
        clientHttpRequestFactory.setConnectTimeout(5 * 1000);
        // 数据读取超时时间(socketTimeout)/毫秒(务器返回数据(response)的时间,超过抛出read timeout)
        clientHttpRequestFactory.setReadTimeout(10 * 1000);
        // 连接池获取请求连接的超时时间,不宜过长,必须设置/毫秒(超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool)
        clientHttpRequestFactory.setConnectionRequestTimeout(10 * 1000);
        return clientHttpRequestFactory;
    }
    
    /**
     * rest模板
     * @return
     */
    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory) {
        // boot中可使用RestTemplateBuilder.build创建
        RestTemplate restTemplate = new RestTemplate();
        // 配置请求工厂
        restTemplate.setRequestFactory(clientHttpRequestFactory);
        return restTemplate;
    }
    
}

4 使用

使用到的实体类如下:

@Data
@ToString
public class TempUser implements Serializable {
    private String userName;   
    private Integer age;
}

4.1 GET请求

后台接口代码:

@RequestMapping("getUser")
public TempUser getUser(TempUser form) {
    TempUser tempUser = new TempUser();
    tempUser.setUserName(form.getUserName());
    tempUser.setAge(form.getAge());
    return tempUser;
}

4.1.1 普通访问

TempUser result = restTemplate.getForObject("http://localhost:8080/cs-admin/rest/getUser?userName=张三&age=18", TempUser.class);

4.1.2 返回HTTP状态

ResponseEntity<TempUser> responseEntity = restTemplate.getForEntity("http://localhost:8080/cs-admin/rest/getUser?userName=张三&age=18", TempUser.class);
// 获取状态对象
HttpStatus httpStatus = responseEntity.getStatusCode();
// 获取状态码
int statusCodeValue = responseEntity.getStatusCodeValue();
// 获取headers
HttpHeaders httpHeaders = responseEntity.getHeaders();
// 获取body
TempUser result = responseEntity.getBody();

4.1.3 映射请求参数

Map<String, Object> paramMap = new HashMap<>();
paramMap.put("userName", "张三");
paramMap.put("age", 18);
TempUser result = restTemplate.getForObject("http://localhost:8080/cs-admin/rest/getUser?userName={userName}&age={age}", TempUser.class, paramMap);

4.2 POST请求

4.2.1 普通访问

后台接口代码:

RequestMapping("getPostUser")
    public TempUser getPostUser(@RequestBody TempUser form) {
    TempUser tempUser = new TempUser();
    tempUser.setUserName(form.getUserName());
    tempUser.setAge(form.getAge());
    return tempUser;
}

(1)普通访问接口

TempUser param = new TempUser();
param.setUserName("张三");
param.setAge(18);
TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/getPostUser", param, TempUser.class);

(2)带HEAD访问接口

// 请求头信息
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("application/json;charset=UTF-8"));
//headers.add("headParam1", "headParamValue");

// 请求体内容
TempUser param = new TempUser();
param.setUserName("张三");
param.setAge(18);

// 组装请求信息
HttpEntity<TempUser> httpEntity=new HttpEntity<>(param,headers);

TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/getPostUser", httpEntity, TempUser.class);

4.2.2 无请求体的访问

仅method为post,传参方式仍然为get的param方式

后台接口代码:

@RequestMapping("getPostUserNoBody")
public TempUser getPostUserNoBody(TempUser form) {
    TempUser tempUser = new TempUser();
    tempUser.setUserName(form.getUserName());
    tempUser.setAge(form.getAge());
    return tempUser;
}

访问方式:

Map<String, Object> paramMap = new HashMap<>();
paramMap.put("userName", "张三");
paramMap.put("age", 18);
TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/getPostUserNoBody?userName={userName}&age={age}", null, TempUser.class, paramMap);
System.out.println(result);

4.3 上传文件

后台接口代码:

@RequestMapping("uploadFile")
public TempUser uploadFile(HttpServletRequest request, TempUser form) {
    MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
    //获取文件信息
    MultipartFile multipartFile = multipartHttpServletRequest.getFile("file");
    TempUser tempUser = new TempUser();
    if (multipartFile != null) {
        tempUser.setUserName(form.getUserName()+" "+multipartFile.getOriginalFilename());
    }
    if(form!=null){
        tempUser.setAge(form.getAge());
    }
    return tempUser;
}

访问方式:

// 文件
FileSystemResource file=new FileSystemResource("D:\\Elasticsearch权威指南(中文版).pdf");

// 设置请求内容
MultiValueMap<String, Object> param=new LinkedMultiValueMap<>();
param.add("file", file);
// 其他参数
param.add("userName", "张三");
param.add("age", 18);

// 组装请求信息
HttpEntity<MultiValueMap<String, Object>> httpEntity=new HttpEntity<>(param);

// 发送请求
TempUser result = restTemplate.postForObject("http://localhost:8080/cs-admin/rest/uploadFile", httpEntity, TempUser.class);

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java 读取本地文件实例详解

    java 读取本地文件实例详解

    这篇文章主要介绍了java 读取本地文件实例详解的相关资料,需要的朋友可以参考下
    2017-05-05
  • Spring Security源码解析之权限访问控制是如何做到的

    Spring Security源码解析之权限访问控制是如何做到的

    Spring Security 中对于权限控制默认已经提供了很多了,但是,一个优秀的框架必须具备良好的扩展性,下面小编给大家介绍Spring Security源码解析之权限访问控制是如何做到的,感兴趣的朋友跟随小编一起看看吧
    2021-05-05
  • 完美解决request请求流只能读取一次的问题

    完美解决request请求流只能读取一次的问题

    这篇文章主要介绍了完美解决request请求流只能读取一次的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Java锁升级机制超详细讲解(附实例代码)

    Java锁升级机制超详细讲解(附实例代码)

    Java中的synchronized锁会经历一个从无锁到偏向锁,再到轻量级锁,最后到重量级锁的升级过程,这种优化称为锁升级或锁膨胀,这篇文章主要介绍了Java锁升级机制超详细讲解的相关资料,需要的朋友可以参考下
    2025-06-06
  • Java Hibernate中的查询策略和抓取策略

    Java Hibernate中的查询策略和抓取策略

    Hibernate是一种Java对象关系映射框架,提供了多种查询和抓取策略,用于优化数据库访问性能。查询策略包括延迟加载、立即加载、查询缓存等,抓取策略包括join抓取、子查询抓取、批量抓取等。这些策略可以根据实际应用场景进行选择和配置,提高数据访问的效率和稳定性
    2023-04-04
  • 使用Java实现价格加密与优化功能

    使用Java实现价格加密与优化功能

    在现代软件开发中,数据加密是一个非常重要的环节,尤其是在处理敏感信息(如价格、用户数据等)时,本文将详细介绍如何使用 Java 实现价格加密,并对代码进行优化,需要的朋友可以参考下
    2025-01-01
  • Springboot使用切面功能详解

    Springboot使用切面功能详解

    Spring Boot 是一个基于Spring框架的项目,它简化了基于Spring的应用开发,这篇文章主要介绍了 Spring Boot 中的切面功能,需要的可以了解下
    2025-01-01
  • 详解java中的static关键字

    详解java中的static关键字

    这篇文章主要介绍了java中的static关键字的的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-06-06
  • Springboot打印接口的三种方式分享

    Springboot打印接口的三种方式分享

    这篇文章主要为大家详细介绍了Springboot打印接口的三种方式:aop切面的方式、过滤器的方式和拦截器的方式,感兴趣的可以跟随小编一起学习一下
    2022-08-08
  • 一文带你掌握Java8强大的StreamAPI

    一文带你掌握Java8强大的StreamAPI

    Java8API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream 使用一种类似用SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码
    2021-10-10

最新评论