凌峰创科服务平台

HttpClient如何设置代理服务器?

核心概念

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

HttpClient如何设置代理服务器?-图1
(图片来源网络,侵删)
  1. HttpHost: 代表一个目标主机或代理服务器,它包含了主机名(或IP地址)和端口号,当用它表示代理时,还需要设置协议(通常是 httphttps)。
  2. RequestConfig: 用于配置单个HTTP请求的详细行为,包括超时时间、连接管理、以及最重要的——代理设置。
  3. 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 应用到 HttpClientHttpGet 请求

有两种主要方式:

为单个请求设置代理(推荐)

HttpClient如何设置代理服务器?-图2
(图片来源网络,侵删)

这种方式更灵活,可以针对不同的请求使用不同的代理。

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

HttpClient如何设置代理服务器?-图3
(图片来源网络,侵删)
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 代理: 默认类型,处理 httphttps 流量。
    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();

常见问题与注意事项

  1. 代理连接失败:

    • 检查代理地址和端口: 确保输入正确。
    • 检查网络: 确保你的机器可以访问代理服务器。
    • 检查防火墙: 本地或网络防火墙可能阻止了连接。
    • 代理服务器是否在线: 代理服务器可能已关闭或不可用。
  2. 代理认证失败:

    • 检查用户名和密码: 确保凭据正确。
    • 区分认证域: AuthScope 的构造函数可以指定主机、端口、协议和 realm,如果代理服务器的 realm 不正确,认证也会失败,通常使用 new AuthScope(host, port) 即可。
  3. NoHttpResponseException:

    • 这通常意味着成功连接到代理,但代理服务器本身无法连接到目标服务器(httpbin.org),这可能是代理服务器的问题,或者目标服务器被代理屏蔽了。
  4. 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();

  5. 不使用代理(绕过代理): 有时你只想为某些特定域名使用代理,或者绕过代理访问本地地址,可以通过 RequestConfigsetProxy() 方法传入 null 来禁用单个请求的代理。

    // 为特定请求不使用代理
    HttpGet bypassProxyRequest = new HttpGet("http://localhost:8080/api");
    RequestConfig noProxyConfig
分享:
扫描分享到社交APP
上一篇
下一篇