Proxy
什么是代理?
local client 向 Proxy Server发出请求,然后Proxy Server再向remote Server发出请求,remote server把结果给proxy,proxy再返回给client。
为什么要用代理?
1,安全考虑。使用代理能对remote server屏蔽client端细节
2,访问控制。proxy可以有过滤的功能,将不想让client访问的站点block掉。
3,性能考虑。多个client请求统一资源时,proxy可以将那个资源缓存,而不用每次都请求remote server。
java程序员可以使用URL类来搞定和绝大部分proxy server或者protocol通信的工作。
System Proxy
System.setProperty("http.proxyHost", "192.168.254.254");
System.setProperty("http.proxyPort", "9000");
System.setProperty("http.nonProxyHosts", "java.oreilly.com|xml.oreilly.com");
如果用http代理,则用http.proxyHost设置代理主机,用http.proxyPort设置代理端口。不想被代理的主机可以用http.nonProxyHosts。
除了使用System.setProperty()外,还可在程序启动时配置参数
java -D http.proxyHost=192.168.254.254 -D http.nonProxyHosts=*.oreilly.com
对ftp协议的,可以用ft p.proxyHost,ftp.proxyPort,ftp.nonProxyHosts。
java对应用层协议代理,只支持这2个。如果想对传输层所有的TCP连接都做Socket代理,socksProxyHost 和 socksProxyPort,但没有nonSocksProxyHosts,all-or-nothing !
ProxyClass
ProxyClass可进行“细粒度”(fine-grained)控制。为不同reomte server选择不同的proxy server。不同的Proxy实例表示不同的代理。
SocketAddress address = new InetSocketAddress("proxy.example.com", 80);
Proxy proxy = new Proxy(Proxy.Type.HTTP, address);
有3种代理
• Proxy.Type.DIRECT
• Proxy.Type.HTTP
• Proxy.Type.SOCKS
ProxySelector Class
每个JVM只有一个ProxySelector实例,用于为不同的connection定位到不同的proxy server。默认的ps只检测一些系统属性(比如上面提到的)和URL协议然后决定如何连接到remote server。
可以自定义以ps,替换掉默认的。
要实现2个方法
public abstract List<Proxy> select(URI uri)
系统根据返回的List<Proxy>去连接remote server。
public void connectFailed(URI uri, SocketAddress address, IOException ex)
该方法是个callback方法,无法连接到proxy server时回调该方法。
public class LocalProxySelector extends ProxySelector {
private List<URI> failed = new ArrayList<URI>();
public List<Proxy> select(URI uri) {
List<Proxy> result = new ArrayList<Proxy>();
if (failed.contains(uri)
|| !"http".equalsIgnoreCase(uri.getScheme())) {
result.add(Proxy.NO_PROXY);
} else {
SocketAddress proxyAddress
= new InetSocketAddress( "proxy.example.com", 8000);
Proxy proxy = new Proxy(Proxy.Type.HTTP, proxyAddress);
result.add(proxy);
}
return result;
}
public void connectFailed(URI uri, SocketAddress address, IOException ex) {
failed.add(uri);
}
}
替换默认的
ProxySelector selector = new LocalProxySelector():
ProxySelector.setDefault(selector);