1.问题描述
笔者做的项目服务:启动在内网环境中,一切外网相关的链接都需要走透明代理。
阿里云sdk:封装好与http相关的所有操作,我们没办法去配置http相关的设置。
针对问题一:内网服务访问外网走代理?
针对问题二:如何在java代码中设置http连接代理?
问题二这就是本篇博文的主题,全文以jdk8作为示例。
2.实现方法
(1)使用System.properties
//使用HTTP
System.setProperty("http.proxyHost", "xxx.xxx.xxx");//填写你的代理ip
System.setProperty("http.proxyPort", "8080");//填写你的代理端口
(oracle相关文档并没有proxySet属性,无需添加)
(如果有相关密码验证,这里不做赘述)
//使用HTTPS
System.setProperty("https.proxyHost", "webcache.example.com");
System.setProperty("https.proxyPort", "443");
//补充,使用http.nonProxyHosts 这个属性中地址会直接访问不会经过代理
System.setProperty("http.nonProxyHosts", "localhost|127.0.0.1|*.local|")
优点:
- 简单快捷,两条语句能够让http连接走代理。
- 前提使用HTTP是不需要更改阿里sdk,没有看到阿里云sdk能够切换http/https的设置。
缺点:
- 一旦设置了全局System代理字段进行设置,所有的连接都会使用代理去访问。当然可以去配置http.nonProxyHosts,但是当系统中有代理访问不到ip时就会有问题了。
那么可以不可以使用完以后关闭代理呢?
System.setProperty("http.proxyHost", "xxx.xxx.xxx");//填写你的代理ip
System.setProperty("http.proxyPort", "8080");//填写你的代理端口
//http请求(使用代理)
System.clearProperty("http.proxyHost");
//http请求(已经没有代理了)
如果你的程序是单线程,那么这样没有问题。
如果程序是多线程,没办法保证在clearProperty之前是否会有别的线程走代理,那么是有问题的。
但是如果代理能够访问到所有线程请求的ip,那么这么做也无妨。
(2)终极解决方案:针对连接使用代理
这里使用Apache的HttpClient作为演示:
HttpHost proxy = new HttpHost(PROXY_IP, PROXY_PORT, "http");
System.out.println("【代理信息】ip:" + PROXY_IP + "port:" + PROXY_PORT);
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000) //设置连接建立超时的时间
.setConnectionRequestTimeout(5000)
.setSocketTimeout(5000)
.setProxy(