Java使用代理进行网络连接方法示例
需求是这样的:
一、界面上要有这样几种代理类型可以选。
1.HTTP代理
2.Socks代理
3.不使用代理(直连)
4.使用浏览器设置(浏览器也是HTTP、Socks、直连三种)。
可参考QQ登录设置里的代理能,其实跟qq的代理功能是一样的。
二、测试使用所填写的代理配置信息是否可连接
三、记录用户上次选择的代理配置,默认使用用户上次使用的代理配置进行网络连接。
程序运行环境是WindowsXP、Windows7、Windows8系统。
使用的技术为Java7,Swing,CXF。
难点:
1.如何进行全居的代理设置:
/**
*网络代理Bean
*
*@authortang
*/
publicclassNetworkBeanimplementsSerializable{
privatestaticfinallongserialVersionUID=1L;
//privatestaticsun.misc.BASE64Encoderbase64Encoder=newsun.misc.BASE64Encoder();
privateProxy.Typetype;//代理类型
privateStringaddress;//ip地址
privateStringport;//端口号
privateStringusername;//代理服务器用户名
privateStringpassword;//代理服务器用户密码
privateStringdomain;//域
privateStringtypeText;//代理类型显示的文本
publicNetworkBean(){
}
publicNetworkBean(Typetype,Stringaddress,Stringport,Stringusername,Stringpassword){
this.type=type;
this.address=address;
this.port=port;
this.username=username;
this.password=password;
}
publicNetworkBean(Typetype,Stringaddress,Stringport,Stringusername,Stringpassword,Stringdomain){
super();
this.type=type;
this.address=address;
this.port=port;
this.username=username;
this.password=password;
this.domain=domain;
}
publicProxy.TypegetType(){
returntype;
}
publicvoidsetType(Proxy.Typetype){
this.type=type;
}
publicStringgetAddress(){
returnaddress;
}
publicvoidsetAddress(Stringaddress){
this.address=address;
}
publicStringgetPort(){
returnport;
}
publicvoidsetPort(Stringport){
this.port=port;
}
publicStringgetUsername(){
returnusername;
}
publicvoidsetUsername(Stringusername){
this.username=username;
}
publicStringgetPassword(){
returnpassword;
}
publicvoidsetPassword(Stringpassword){
this.password=password;
}
publicStringgetDomain(){
returndomain;
}
publicvoidsetDomain(Stringdomain){
this.domain=domain;
}
publicStringgetTypeText(){
returntypeText;
}
publicvoidsetTypeText(StringtypeText){
this.typeText=typeText;
}
/**
*returndomain+"\"+username
*/
publicStringgetDomainAndUsername(){
return(Utils.toString(domain).trim().isEmpty())?username:domain.trim()+"\\"+username;
}
/**
*returndomain+"\"+username+":"+password
*/
publicStringgetDomainAndUsernameAndPassword(){
returngetDomainAndUsername()+":"+password;
}
/**
*returnusername+":"+password
*/
publicStringgetUsernameAndPassword(){
returnusername+":"+password;
}
/**
*return(domain+"\"+username+":"+password)to64bit
*/
publicStringgetDomainAndUsernameAndPassword64(){
returnorg.apache.commons.codec.binary.Base64.encodeBase64String(getDomainAndUsernameAndPassword().getBytes());
}
@Override
publicStringtoString(){
return"NetworkBean[type="+type+",typeText="+typeText+",address="+address+",port="+port+",username="+username+",password="
+password+",domain="+domain+"]";
}
}
/**
*根据指定的代理信息设置系统全局的网络代理
*
*@paramnetworkBean
*/
publicstaticvoidsetNetworkProxyBySystem(NetworkBeannetworkBean){
System.out.println("SystemSetProxy:"+networkBean);
if(isUserProxy(networkBean)){
if(networkBean.getType()==Proxy.Type.SOCKS){
System.getProperties().remove("http.proxyHost");
System.getProperties().remove("http.proxyPort");
System.getProperties().setProperty("socksProxyHost",networkBean.getAddress());
System.getProperties().setProperty("socksProxyPort",networkBean.getPort());
}else{
System.getProperties().setProperty("http.proxyHost",networkBean.getAddress());
System.getProperties().setProperty("http.proxyPort",networkBean.getPort());
}
Authenticator.setDefault(newBairuiAuthenticator(networkBean.getDomainAndUsername(),networkBean.getPassword()));
}elseif(networkBean!=null){
System.getProperties().remove("proxySet");
System.getProperties().remove("socksProxySet");
System.getProperties().remove("http.proxyHost");
System.getProperties().remove("http.proxyPort");
System.getProperties().remove("socksProxyHost");
System.getProperties().remove("socksProxyPort");
}
}
/**
*网络用户名密码校验提供者
*/
publicstaticclassBairuiAuthenticatorextendsAuthenticator{
privateStringusername,password;
publicBairuiAuthenticator(Stringusername,Stringpassword){
this.username=username;
this.password=password;
}
protectedPasswordAuthenticationgetPasswordAuthentication(){
returnnewPasswordAuthentication(username,password==null?null:password.toCharArray());
}
}
2.如何让CXF的Service使用系统的代理:
/**
*为WebService接口添加网络代理支持:httpClientPolicy.setAllowChunking(false);
*
*@paramclient
*/
publicstaticvoidsetWebServiceSupportProxy(Clientclient){
HTTPConduitconduit=(HTTPConduit)client.getConduit();
HTTPClientPolicyhttpClientPolicy=newHTTPClientPolicy();
httpClientPolicy.setAllowChunking(false);
conduit.setClient(httpClientPolicy);
}
3.使用浏览器设置:
/**
*读取用户注册表获取浏览器的代理设置
*
*@return该方法不会返回null值也不会抛出异常
*/
publicstaticNetworkBeangetBrowserProxy(){
NetworkBeannetworkBean=newNetworkBean();
networkBean.setTypeText(typeTexts[3]);
networkBean.setType(Proxy.Type.DIRECT);
Stringkey="regquery\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\InternetSettings\"";//注册表浏览器代理key
try{
Processexec=Runtime.getRuntime().exec(key);
try(InputStreamReaderi=newInputStreamReader(exec.getInputStream());BufferedReaderir=newBufferedReader(i)){
for(Stringline=ir.readLine();line!=null;line=ir.readLine()){
if(line.indexOf("ProxyServer")>=0){
String[]split1=line.split("");
if(split1.length>3){
String[]split2=split1[3].trim().split(":");
if(split2.length>1){
if(!Utils.toString(split2[0]).isEmpty()&&!Utils.toString(split2[1]).isEmpty()){
networkBean.setAddress(split2[0]);
networkBean.setPort(split2[1]);
networkBean.setType(Proxy.Type.HTTP);
break;
}
}
}
}
}
}catch(Exceptione){
e.printStackTrace();
}
}catch(Exceptione){//从注册表读取失败
e.printStackTrace();
}
returnnetworkBean;
}
4.测试代理是否可用
因为程序中使用了服务器的两个不同的端口,所以需要测试两个端口是否都可连。
如果使用了多台服务器,更加需要分别测试了。
/**
*测试网络代理是否能通过连接,如果不通过抛出异常
*
*@throwsException
*/
privatestaticvoidtestNetworkProxy()throwsException{
testWebService();
testURLConnection();
}
/**
*测试CXFService接口50367端口
*
*@paramnetworkBean
*@throwsException
*/
publicstaticvoidtestWebService()throwsException{
JcptLoginServiceservice=WebServiceUtils.getService(JcptLoginService.class,GeneralWebServiceAddress.LOGIN_SERVICE_URL_ADD);
Stringresult=service.getLoginPicture();
System.out.println(result);
}
/**
*从HttpURLConnection对象读取指定字符,如果不匹配则抛出异常
*
*@paramconnection
*@throwsException
*/
privatestaticvoidcheckConnectionContent(HttpURLConnectionconnection)throwsException{
try(InputStreaminputStream=connection.getInputStream()){
byte[]b=newbyte[1024];
booleansuccess=false;
StringBuffersb=newStringBuffer();
for(inti=inputStream.read(b);i>0;i=inputStream.read(b)){
StringtempStr=newString(b,0,i);
sb.append(tempStr);
if(tempStr.indexOf("3,filenotfound")>=0){//service固定返回这个字符串,如果service作了更改此处也应更改
success=true;
break;
}
}
if(!success){
Stringstr=sb.toString();
if(str.length()>3){
charchar0=str.charAt(0);
charchar1=str.charAt(1);
if(Utils.isNumber(char0+"")&&char1==','){
success=true;
}
}
}
if(!success){
thrownewRuntimeException("resultcontentdoesnotmeetexpectations.");
}
}catch(Exceptionex){
throwex;
}
}
/**
*测试文件下载接口9067端口
*
*@paramnetworkBean
*@throwsException
*/
publicstaticvoidtestURLConnection()throwsException{
HttpURLConnectionconnection=(HttpURLConnection)newURL(GeneralWebServiceAddress.FILE_DOWN_URL_ADD+"path=").openConnection();
checkConnectionContent(connection);
}
/**
*测试代理服务器连接
*/
privatevoidtestProxyConnection(){
NetworkBeanreadNetworkBean=NetworkProxyTool.readNetworkBean();//先获得正在使用的NetworkBean
try{
NetworkBeannetworkBean=createNetworkBean();//根据用户填写的信息创建的NetworkBean对象
showTestResultDialog(NetworkProxyTool.testNetworkProxyBySystem(networkBean));
}catch(Exceptionex){
showTestResultDialog(false);
}
NetworkProxyTool.setNetworkProxyBySystem(readNetworkBean);//测试结束,还原原来的NetworkBean
}
5.因为java连接网络时,如果使用当前的代理连接失败,那么就会使用操作系统中缓存的代理进行网络连接,如何是测试连接时不使用操作系统缓存,但测试结束后使用操作系统缓存。
/**
*设置长连接和验证信息缓存是否开启
*
*@paramkeepAlive
*/
publicstaticvoidsetKeepAliveAndAuthCache(booleankeepAlive){
System.setProperty("http.keepAlive",keepAlive+"");//设置是否开始长连接,如果为false可以防止连接被缓存(如果连接被缓存,用户名密码等所有信息都会被缓存)
if(keepAlive){
AuthCacheValue.setAuthCache(newAuthCacheImpl());
}else{
//设置一个空的实现AuthCache可以防止用户名密码信息被缓存
AuthCacheValue.setAuthCache(newAuthCache(){
publicvoidremove(Stringpkey,AuthCacheValueentry){
}
publicvoidput(Stringpkey,AuthCacheValuevalue){
}
publicAuthCacheValueget(Stringpkey,Stringskey){
returnnull;
}
});
}
}
在登录之前:
NetworkProxyTool.setKeepAliveAndAuthCache(false); new.Login();
登录成功后:
NetworkProxyTool.setKeepAliveAndAuthCache(true);
6.保存用户的代理配置:
因为直接序列化自定义类型的对象,会存在版本问题(比如这个类的包名、类名改了,就死定了)。
所以不能直接序列化自定义类的对象,二是将自定义类对象的属性转成字典(Map),然后序列化map。
/**
*读取本地网络代理设置配置文件
*
*@return
*/
publicstaticNetworkBeanreadNetworkBean(){
NetworkBeannetworkBean=getCurrNetworkBean(readNetworkBeanMap());
if(networkBean==null){
networkBean=newNetworkBean();
networkBean.setType(Proxy.Type.DIRECT);
}
returnnetworkBean;
}
/**
*获取用户上次选择网络代理设置
*
*@parammap
*@return
*/
publicstaticNetworkBeangetCurrNetworkBean(Mapmap){
putBrowserProxy(map);
return(NetworkBean)map.get(getTypeMapKey(map));
}
/**
*将浏览器的信息存放入代理信息总配置map
*
*@parammap
*/
privatestaticvoidputBrowserProxy(Mapmap){
if(browserProxyBean==null){
browserProxyBean=getBrowserProxy();
}
NetworkBeannetworkBeanBrowser=(NetworkBean)map.get(key_browser);
if(networkBeanBrowser==null){
networkBeanBrowser=browserProxyBean;
}
if((Utils.toString(browserProxyBean.getAddress()).isEmpty()||!browserProxyBean.getAddress().equals(networkBeanBrowser.getAddress()))
||(Utils.toString(browserProxyBean.getPort()).isEmpty()||!browserProxyBean.getPort().equals(networkBeanBrowser.getPort()))){
networkBeanBrowser.setUsername(null);
networkBeanBrowser.setPassword(null);
networkBeanBrowser.setDomain(null);
}
networkBeanBrowser.setType(browserProxyBean.getType());
networkBeanBrowser.setTypeText(browserProxyBean.getTypeText());
networkBeanBrowser.setAddress(browserProxyBean.getAddress());
networkBeanBrowser.setPort(browserProxyBean.getPort());
map.put(key_browser,networkBeanBrowser);
}  
在登录之前:
NetworkBeannetworkBean=NetworkProxyTool.readNetworkBean(); NetworkProxyTool.setNetworkProxyBySystem(networkBean); NetworkProxyTool.setKeepAliveAndAuthCache(false); new.Login();
在用户配置完代理点击确定时:
/**
*点击确定
*/
privatevoidconfirm(){
if((isHttp()||isSocks())&&!checkIpAndPortNotNull()){
return;
}
NetworkBeannetworkBean=createNetworkBean();
if(isHttp()){//HTTP代理
if(networkBean.getDomain()!=null){
networkBean.setDomain(networkBean.getDomain().trim());
}
proxySettingMap.put(key_http,networkBean);
proxySettingMap.put(key_proxy_type,key_http);
}elseif(isSocks()){//SOCKS代理
proxySettingMap.put(key_socks,networkBean);
proxySettingMap.put(key_proxy_type,key_socks);
}elseif(isBrowser()){
proxySettingMap.put(key_browser,networkBean);
proxySettingMap.put(key_proxy_type,key_browser);
}else{
proxySettingMap.put(key_direct,networkBean);
proxySettingMap.put(key_proxy_type,key_direct);
}
userCurrShowNetworkBean=networkBean;
isConfirm=true;
setVisible(false);
NetworkProxyTool.saveNetworkProxyConfig(proxySettingMap);
}
SystemProperties
JavaSystemProperties网络设置有哪些key
http://docs.oracle.com/javase/7/docs/technotes/guides/net/properties.html
http://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html
JavaSystemProperties优先级说明
host和port比set优先级高,也就是说set可以不用去设置。
如存在http.proxyHost和http.proxyPort时,proxySet设为false无效,系统仍然可以使用http代理。
存在socksProxyHost和socksProxyPort时,socksProxySet设为false无效,系统仍然可以使用socks代理。
http比socks优先级高,即存在http.proxyHost和http.proxyPort时,socksProxySet、socksProxyHost、socksProxyPort都会失效,系统会使用http代理。
使用java.net.Proxy
如果只是单个的连接需要使用代理,那么可以采用Proxy类进行代理连接。
说明:
1.Socket只能使用socks代理不能使用http代理。
2.Socket使用使用Authenticator来进行验证。
3.URLConnection使用RequestProperty是只对当前连接有效,不会缓存,Authenticator是全局性的,对所有网络请求都有效,会缓存,但RequestProperty的优先级比Authenticator高。
4.只有RequestProperty需要64位编码,Authenticator不需要。
5.需要清除验证缓存的,不使用验证缓存上面已经有代码了,这里就不重复写了。
6.其实,建议采用全局性的代理连接,不管是URLConnection还是Socket都简单方便、统一。
代码:
NetworkBeanhttpBean=newNetworkBean(Proxy.Type.HTTP,"192.168.77.5","8888","tzc","123",null);
ProxyhttpProxy=newProxy(httpBean.getType(),newInetSocketAddress(httpBean.getAddress(),Integer.parseInt(httpBean.getPort())));
NetworkBeansocksBean=newNetworkBean(Proxy.Type.SOCKS,"192.168.77.5","9999","tzc","123","ttt");
ProxysocksProxy=newProxy(socksBean.getType(),newInetSocketAddress(socksBean.getAddress(),Integer.parseInt(socksBean.getPort())));
URLConnectionhttpProxyConnection=newURL("http://www.baidu.com/").openConnection(httpProxy);
//或者Authenticator.setDefault(newBairuiAuthenticator(networkBean.getDomainAndUsername(),networkBean.getPassword()));
httpProxyConnection.setRequestProperty("Proxy-Authorization","Basic"+httpBean.getDomainAndUsernameAndPassword64());
URLConnectionsocksProxyConnection=newURL("http://www.baidu.com/").openConnection(socksProxy);
//或者Authenticator.setDefault(newBairuiAuthenticator(networkBean.getDomainAndUsername(),networkBean.getPassword()));
socksProxyConnection.setRequestProperty("Proxy-Authorization","Basic"+httpBean.getDomainAndUsernameAndPassword64());
Socketsocket=newSocket(socksProxy);
Authenticator.setDefault(newBairuiAuthenticator(networkBean.getDomainAndUsername(),networkBean.getPassword()));
socket.connect(newInetSocketAddress("www.baidu.com",5555));
总结
以上就是本文关于Java使用代理进行网络连接方法示例的全部内容,希望对大家学习Java有所帮助,欢迎各位浏览本站其他专题并随时留言,小编会及时回复大家的。