1. 概述

在本篇短小精悍的教程中,我们将探讨如何通过 Spring 的 RestTemplate 发送请求到代理服务器。这在企业级应用中很常见,比如需要通过公司统一出口代理访问外部服务时,或者测试环境下模拟网络链路。

✅ 核心目标:让 RestTemplate 的 HTTP 请求走指定代理
⚠️ 注意:本文不涉及 SOCKS 代理,仅聚焦 HTTP/HTTPS 代理场景

2. 依赖配置

要支持更灵活的代理控制,尤其是使用 Apache HttpClient 的高级功能(如路由规划),我们需要引入 httpcore5 依赖。

如果你使用的是 Maven,在 pom.xml 中添加:

<dependency>
    <groupId>org.apache.httpcomponents.core5</groupId>
    <artifactId>httpcore5</artifactId>
    <version>5.2.1</version>
</dependency>

Gradle 用户则在 build.gradle 中加入:

implementation 'org.apache.httpcomponents.core5:httpcore5:5.2.1'

⚠️ 踩坑提醒:注意是 httpcore5 而非旧版 httpclient,版本号也需匹配 Spring Boot 所支持的范围,避免类加载冲突。

3. 使用 SimpleClientHttpRequestFactory 配置代理

这是最简单粗暴的方式,适合快速验证或非 Spring Boot 环境。

关键思路:
✅ 通过 SimpleClientHttpRequestFactory.setProxy() 设置 JDK 原生 java.net.Proxy 实例
✅ 将该 factory 传入 RestTemplate 构造函数

步骤如下:

  1. 创建代理配置对象:
Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress("proxy.company.com", 8080));
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setProxy(proxy);
  1. 构建带代理能力的 RestTemplate
RestTemplate restTemplate = new RestTemplate(requestFactory);
  1. 发起请求验证代理是否生效:
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://httpbin.org/get", String.class);

assertThat(responseEntity.getStatusCode(), is(equalTo(HttpStatus.OK)));

✅ 优点:代码少,理解成本低
❌ 缺点:无法精细控制连接池、超时、SSL 等参数;依赖 JDK 原生实现,灵活性差

4. 使用 RestTemplateCustomizer 配置代理(推荐)

在 Spring Boot 场景下,官方更推荐使用 RestTemplateBuilder + RestTemplateCustomizer 的方式。它不仅更符合自动装配的设计理念,还能与其他定制化逻辑组合使用。

实现步骤:

  1. 定义一个代理定制器:
class ProxyCustomizer implements RestTemplateCustomizer {

    @Override
    public void customize(RestTemplate restTemplate) {
        HttpHost proxy = new HttpHost("proxy.company.com", 8080);
        HttpClient httpClient = HttpClientBuilder.create()
            .setRoutePlanner(new DefaultProxyRoutePlanner(proxy))
            .build();
        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
    }
}

📌 解释:

  • 使用 Apache HttpClient 的 HttpHost 明确指定代理主机和端口
  • DefaultProxyRoutePlanner 自动将所有请求路由到该代理
  • 最终通过 HttpComponentsClientHttpRequestFactory 接管请求工厂,获得完整 HttpClient 控制权
  1. 使用 RestTemplateBuilder 构建实例:
RestTemplate restTemplate = new RestTemplateBuilder(new ProxyCustomizer()).build();
  1. 正常发起请求即可走代理:
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://httpbin.org/get", String.class);
assertThat(responseEntity.getStatusCode(), is(equalTo(HttpStatus.OK)));

✅ 优点:

  • 更灵活,可扩展性强(比如后续加认证、连接池等)
  • 与 Spring Boot 自动配置体系兼容良好
  • 支持细粒度调优(超时、重试、SSL 策略等)

❌ 缺点:代码略多,初学者可能觉得绕

⚠️ 踩坑提醒:确保 HttpComponentsClientHttpRequestFactory 来自 spring-web 模块,不要手动管理 HttpClient 生命周期,避免资源泄漏。

5. 总结

本文介绍了两种通过 RestTemplate 配置代理的方式:

方式 适用场景 推荐程度
SimpleClientHttpRequestFactory + setProxy 快速原型、简单需求 ⚠️ 一般
RestTemplateCustomizer + RestTemplateBuilder 生产环境、Spring Boot 项目 ✅ 强烈推荐

📌 最佳实践建议:

  • Spring Boot 项目一律优先使用 RestTemplateCustomizer
  • 若需代理认证(Basic Auth),可在 HttpClientBuilder 中添加 setDefaultCredentialsProvider
  • 注意代理服务器的稳定性与超时设置匹配,避免雪崩

🔗 示例代码已托管至 GitHub:https://github.com/baeldung/spring-resttemplate-2


原始标题:Proxies With RestTemplate | Baeldung