核心概念
在 HttpClient 中,代理的设置主要围绕 HttpHost 对象和 RequestConfig 对象展开。

HttpHost: 代表一个目标主机或代理服务器,它包含了主机名(或IP地址)和端口号,当用它表示代理时,还需要设置协议(通常是http或https)。RequestConfig: 用于配置单个HTTP请求的详细行为,包括超时时间、连接管理、以及最重要的——代理设置。HttpClient: 在执行请求时,会使用关联的RequestConfig来决定是否以及如何通过代理服务器发送请求。
基本步骤:如何设置代理
下面是最核心、最常用的设置代理的方法。
添加 Maven 依赖
确保你的项目包含了 HttpClient 的依赖,这里以 4.x 版本为例,5.x 版本 API 有些许不同,但概念相似。
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version> <!-- 使用较新的稳定版本 -->
</dependency>
创建代理服务器 HttpHost 对象
// 代理服务器地址和端口 String proxyHost = "your.proxy.com"; int proxyPort = 8080; // 创建一个 HttpHost 对象来代表代理服务器 HttpHost proxy = new HttpHost(proxyHost, proxyPort);
创建 RequestConfig 并设置代理
// 创建 RequestConfig,并设置代理
RequestConfig config = RequestConfig.custom()
.setProxy(proxy) // 设置代理
.build();
将 RequestConfig 应用到 HttpClient 和 HttpGet 请求
有两种主要方式:
为单个请求设置代理(推荐)

这种方式更灵活,可以针对不同的请求使用不同的代理。
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class HttpClientProxyExample {
public static void main(String[] args) throws Exception {
// 1. 定义代理
HttpHost proxy = new HttpHost("your.proxy.com", 8080);
// 2. 创建 RequestConfig
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.setConnectTimeout(5000) // 连接超时
.setSocketTimeout(5000) // 请求超时
.build();
// 3. 创建 HttpClient,可以在这里设置默认的 RequestConfig
try (CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(config)
.build()) {
// 4. 创建 HttpGet 请求
HttpGet httpGet = new HttpGet("http://httpbin.org/ip");
// 5. 执行请求并获取响应
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
// 6. 处理响应
String result = EntityUtils.toString(response.getEntity());
System.out.println("Response: " + result);
}
}
}
}
为所有请求设置默认代理
如果你的 HttpClient 实例需要一直使用同一个代理,可以这样设置。
// 创建 HttpClient 时设置默认的 RequestConfig
RequestConfig defaultConfig = RequestConfig.custom()
.setProxy(new HttpHost("your.proxy.com", 8080))
.build();
try (CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(defaultConfig)
.build()) {
// 之后通过这个 httpClient 发起的任何请求都会默认使用这个代理
HttpGet httpGet = new HttpGet("http://httpbin.org/ip");
// ... execute ...
}
高级配置:认证代理
如果你的代理服务器需要用户名和密码进行认证,你需要使用 CredentialsProvider。

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
public class HttpClientAuthenticatedProxyExample {
public static void main(String[] args) throws Exception {
// 1. 定义代理
HttpHost proxy = new HttpHost("your.proxy.com", 8080);
// 2. 创建凭证提供者
CredentialsProvider credsProvider = new BasicCredentialsProvider();
// 设置代理服务器的认证凭据
credsProvider.setCredentials(
new AuthScope(proxy.getHostName(), proxy.getPort()),
new UsernamePasswordCredentials("username", "password"));
// 3. 创建 RequestConfig
RequestConfig config = RequestConfig.custom()
.setProxy(proxy)
.build();
// 4. 创建 HttpClient 并设置凭证提供者和默认配置
try (CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider)
.setDefaultRequestConfig(config)
.build()) {
// 5. 创建请求并执行
HttpGet httpGet = new HttpGet("http://httpbin.org/ip");
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
String result = org.apache.http.util.EntityUtils.toString(response.getEntity());
System.out.println("Response: " + result);
}
}
}
}
不同类型的代理
HttpClient 支持多种代理协议,主要通过 HttpHost 的构造函数或 setScheme 方法指定。
- HTTP 代理: 默认类型,处理
http和https流量。HttpHost httpProxy = new HttpHost("proxy.example.com", 3128, "http"); - SOCKS 代理: 需要额外的依赖
httpclient-proxy。<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient-proxy</artifactId> <version>4.5.13</version> </dependency>// 需要 SocksSocketFactory HttpHost socksProxy = new HttpHost("socks-proxy.example.com", 1080, "socks"); RequestConfig config = RequestConfig.custom() .setProxy(socksProxy) .build();
常见问题与注意事项
-
代理连接失败:
- 检查代理地址和端口: 确保输入正确。
- 检查网络: 确保你的机器可以访问代理服务器。
- 检查防火墙: 本地或网络防火墙可能阻止了连接。
- 代理服务器是否在线: 代理服务器可能已关闭或不可用。
-
代理认证失败:
- 检查用户名和密码: 确保凭据正确。
- 区分认证域:
AuthScope的构造函数可以指定主机、端口、协议和 realm,如果代理服务器的 realm 不正确,认证也会失败,通常使用new AuthScope(host, port)即可。
-
NoHttpResponseException:- 这通常意味着成功连接到代理,但代理服务器本身无法连接到目标服务器(
httpbin.org),这可能是代理服务器的问题,或者目标服务器被代理屏蔽了。
- 这通常意味着成功连接到代理,但代理服务器本身无法连接到目标服务器(
-
SSLHandshakeException:- 如果通过HTTP代理访问HTTPS网站,可能会出现SSL错误,这是因为代理服务器(特别是透明代理)可能会进行中间人攻击,导致证书验证失败,在生产环境中,通常需要配置SSL上下文来信任代理的证书,但这会增加安全风险,对于开发测试,可以尝试禁用主机名验证和信任所有证书(不推荐用于生产环境)。
// 仅用于开发测试! SSLContext sslContext = SSLContextBuilder.create() .loadTrustMaterial((chain, authType) -> true) // 信任所有证书 .build(); SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(sslSocketFactory) .setDefaultRequestConfig(config) .build();
- 如果通过HTTP代理访问HTTPS网站,可能会出现SSL错误,这是因为代理服务器(特别是透明代理)可能会进行中间人攻击,导致证书验证失败,在生产环境中,通常需要配置SSL上下文来信任代理的证书,但这会增加安全风险,对于开发测试,可以尝试禁用主机名验证和信任所有证书(不推荐用于生产环境)。
-
不使用代理(绕过代理): 有时你只想为某些特定域名使用代理,或者绕过代理访问本地地址,可以通过
RequestConfig的setProxy()方法传入null来禁用单个请求的代理。// 为特定请求不使用代理 HttpGet bypassProxyRequest = new HttpGet("http://localhost:8080/api"); RequestConfig noProxyConfig
