为何JVM启动参数设置HttpClient代理失败,代码设置却正常?
问题:JVM代理参数在Apache HttpClient 4.5.13中不生效?
问题场景
- 直接通过代码设置代理时,请求可正常运行:
HttpHost proxy = new HttpHost(properties.getProxyHost(), properties.getProxyPort()); RequestConfig config = RequestConfig.custom() .setProxy(proxy) .build(); URI uri = new URIBuilder(properties.getUri()) .build(); HttpGet request = new HttpGet(uri); request.setConfig(config); HttpResponse response = client.execute(request);
- 通过JVM启动参数设置代理后,请求报错:
JVM启动参数:
java \ ${JAVA_OPTS} \ -Dhttp.proxyHost=my-proxy \ -Dhttp.proxyPort=my-port \ -jar ${PROJECT_DIR}/${TARGET_JAR} \
请求代码:
URI uri = new URIBuilder(properties.getUri()) .build(); HttpGet request = new HttpGet(uri); HttpResponse response = client.execute(request);
报错信息:
I/O exception (java.net.SocketException) caught when processing request to {s}->https://site-address:443: Network is unreachable (connect failed)
依赖版本:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
原因分析
Apache HttpClient 4.x 默认不会自动读取JVM的系统代理参数,它有独立的代理配置机制:
- 手动通过
RequestConfig设置代理,是直接给HttpClient指定了请求层面的代理规则,属于HttpClient自身的配置体系,会被直接应用。 - JVM的
http.proxyHost/http.proxyPort参数是为JDK原生URLConnection设计的,HttpClient默认不兼容这套配置逻辑。即使设置了这些JVM参数,HttpClient也不会自动加载并应用,导致请求未走代理,最终触发网络不可达错误。
另外补充:如果目标地址是HTTPS,JVM层面还需要配套设置-Dhttps.proxyHost和-Dhttps.proxyPort,但即使设置了,HttpClient默认依然不会读取这些参数。
解决方案
方案1:让HttpClient自动读取系统代理参数
在构建HttpClient实例时,配置SystemDefaultRoutePlanner,它会自动读取JVM的代理系统属性:
import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.SystemDefaultRoutePlanner; import java.net.ProxySelector; // 构建HttpClient时添加路由规划器 HttpClient client = HttpClientBuilder.create() .setRoutePlanner(new SystemDefaultRoutePlanner(ProxySelector.getDefault())) .build();
方案2:手动读取系统属性配置代理
自己从系统属性中提取代理信息,手动设置到RequestConfig中(可设置为全局默认配置):
import org.apache.http.client.config.RequestConfig; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.HttpHost; // 从系统属性获取代理信息 String proxyHost = System.getProperty("http.proxyHost"); int proxyPort = Integer.parseInt(System.getProperty("http.proxyPort", "80")); HttpHost proxy = new HttpHost(proxyHost, proxyPort); // 构建全局默认请求配置 RequestConfig defaultConfig = RequestConfig.custom() .setProxy(proxy) .build(); // 给HttpClient设置默认配置 HttpClient client = HttpClientBuilder.create() .setDefaultRequestConfig(defaultConfig) .build();
内容的提问来源于stack exchange,提问作者gjin
相关产品推荐
相关产品推荐

