需求是这样的:
一、界面上要有这样几种代理类型可以选。
1.HTTP代理
2.Socks代理
3.不使用代理(直连)
4.使用浏览器设置(浏览器也是HTTP、Socks、直连三种)。
可参考QQ登录设置里的代理能,其实跟qq的代理功能是一样的。
二、测试使用所填写的代理配置信息是否可连接
三、记录用户上次选择的代理配置,默认使用用户上次使用的代理配置进行网络连接。
程序运行环境是WindowsXP、Windows7、Windows8系统。
使用的技术为Java7,Swing,CXF。
难点:
1.如何进行全居的代理设置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
/** * 网络代理Bean * * @author tang */ public class NetworkBean implements Serializable { private static final long serialVersionUID = 1L; // private static sun.misc.BASE64Encoder base64Encoder = new sun.misc.BASE64Encoder(); private Proxy.Type type; // 代理类型 private String address; // ip 地址 private String port; // 端口号 private String username; // 代理服务器用户名 private String password; // 代理服务器用户密码 private String domain; // 域 private String typeText; // 代理类型显示的文本 public NetworkBean() { } public NetworkBean(Type type, String address, String port, String username, String password) { this .type = type; this .address = address; this .port = port; this .username = username; this .password = password; } public NetworkBean(Type type, String address, String port, String username, String password, String domain) { super (); this .type = type; this .address = address; this .port = port; this .username = username; this .password = password; this .domain = domain; } public Proxy.Type getType() { return type; } public void setType(Proxy.Type type) { this .type = type; } public String getAddress() { return address; } public void setAddress(String address) { this .address = address; } public String getPort() { return port; } public void setPort(String port) { this .port = port; } public String getUsername() { return username; } public void setUsername(String username) { this .username = username; } public String getPassword() { return password; } public void setPassword(String password) { this .password = password; } public String getDomain() { return domain; } public void setDomain(String domain) { this .domain = domain; } public String getTypeText() { return typeText; } public void setTypeText(String typeText) { this .typeText = typeText; } /** * return domain + "\" + username */ public String getDomainAndUsername() { return (Utils.toString(domain).trim().isEmpty()) ? username : domain.trim() + "\\" + username; } /** * return domain + "\" + username + ":" + password */ public String getDomainAndUsernameAndPassword() { return getDomainAndUsername() + ":" + password; } /** * return username + ":" + password */ public String getUsernameAndPassword() { return username + ":" + password; } /** * return (domain + "\" + username + ":" + password) to 64 bit */ public String getDomainAndUsernameAndPassword64() { return org.apache.commons.codec.binary.Base64.encodeBase64String(getDomainAndUsernameAndPassword().getBytes()); } @Override public String toString() { return "NetworkBean [type=" + type + ", typeText=" + typeText + ", address=" + address + ", port=" + port + ", username=" + username + ", password=" + password + ", domain=" + domain + "]" ; } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
/** * 根据指定的代理信息设置系统全局的网络代理 * * @param networkBean */ public static void setNetworkProxyBySystem(NetworkBean networkBean) { System.out.println( "System Set Proxy : " + 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( new BairuiAuthenticator(networkBean.getDomainAndUsername(), networkBean.getPassword())); } else if (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" ); } } /** * 网络用户名密码校验提供者 */ public static class BairuiAuthenticator extends Authenticator { private String username, password; public BairuiAuthenticator(String username, String password) { this .username = username; this .password = password; } protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password == null ? null : password.toCharArray()); } } |
2.如何让CXF的Service使用系统的代理:
1
2
3
4
5
6
7
8
9
10
11
|
/** * 为WebService接口添加网络代理支持:httpClientPolicy.setAllowChunking(false); * * @param client */ public static void setWebServiceSupportProxy(Client client) { HTTPConduit conduit = (HTTPConduit) client.getConduit(); HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy(); httpClientPolicy.setAllowChunking( false ); conduit.setClient(httpClientPolicy); } |
3.使用浏览器设置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
/** * 读取用户注册表获取浏览器的代理设置 * * @return 该方法不会返回null值也不会抛出异常 */ public static NetworkBean getBrowserProxy() { NetworkBean networkBean = new NetworkBean(); networkBean.setTypeText(typeTexts[ 3 ]); networkBean.setType(Proxy.Type.DIRECT); String key = "reg query \"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\"" ; // 注册表浏览器代理key try { Process exec = Runtime.getRuntime().exec(key); try (InputStreamReader i = new InputStreamReader(exec.getInputStream()); BufferedReader ir = new BufferedReader(i)) { for (String line = 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 (Exception e) { e.printStackTrace(); } } catch (Exception e) { // 从注册表读取失败 e.printStackTrace(); } return networkBean; } |
4.测试代理是否可用
因为程序中使用了服务器的两个不同的端口,所以需要测试两个端口是否都可连。
如果使用了多台服务器,更加需要分别测试了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
/** * 测试网络代理是否能通过连接,如果不通过抛出异常 * * @throws Exception */ private static void testNetworkProxy() throws Exception { testWebService(); testURLConnection(); } /** * 测试CXF Service接口50367端口 * * @param networkBean * @throws Exception */ public static void testWebService() throws Exception { JcptLoginService service = WebServiceUtils.getService(JcptLoginService. class , GeneralWebServiceAddress.LOGIN_SERVICE_URL_ADD); String result = service.getLoginPicture(); System.out.println(result); } /** * 从HttpURLConnection对象读取指定字符,如果不匹配则抛出异常 * * @param connection * @throws Exception */ private static void checkConnectionContent(HttpURLConnection connection) throws Exception { try (InputStream inputStream = connection.getInputStream()) { byte [] b = new byte [ 1024 ]; boolean success = false ; StringBuffer sb = new StringBuffer(); for ( int i = inputStream.read(b); i > 0 ; i = inputStream.read(b)) { String tempStr = new String(b, 0 , i); sb.append(tempStr); if (tempStr.indexOf( "3,file not found" ) >= 0 ) { // service固定返回这个字符串,如果service作了更改此处也应更改 success = true ; break ; } } if (!success) { String str = sb.toString(); if (str.length() > 3 ) { char char0 = str.charAt( 0 ); char char1 = str.charAt( 1 ); if (Utils.isNumber(char0 + "" ) && char1 == ',' ) { success = true ; } } } if (!success) { throw new RuntimeException( "result content does not meet expectations." ); } } catch (Exception ex) { throw ex; } } /** * 测试文件下载接口9067端口 * * @param networkBean * @throws Exception */ public static void testURLConnection() throws Exception { HttpURLConnection connection = (HttpURLConnection) new URL(GeneralWebServiceAddress.FILE_DOWN_URL_ADD + "path=" ).openConnection(); checkConnectionContent(connection); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
|
/** * 测试代理服务器连接 */ private void testProxyConnection() { NetworkBean readNetworkBean = NetworkProxyTool.readNetworkBean(); // 先获得正在使用的NetworkBean try { NetworkBean networkBean = createNetworkBean(); // 根据用户填写的信息创建的NetworkBean对象 showTestResultDialog(NetworkProxyTool.testNetworkProxyBySystem(networkBean)); } catch (Exception ex) { showTestResultDialog( false ); } NetworkProxyTool.setNetworkProxyBySystem(readNetworkBean); // 测试结束,还原原来的NetworkBean } |
5.因为java连接网络时,如果使用当前的代理连接失败,那么就会使用操作系统中缓存的代理进行网络连接,如何是测试连接时不使用操作系统缓存,但测试结束后使用操作系统缓存。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/** * 设置长连接和验证信息缓存是否开启 * * @param keepAlive */ public static void setKeepAliveAndAuthCache( boolean keepAlive) { System.setProperty( "http.keepAlive" , keepAlive + "" ); // 设置是否开始长连接,如果为false可以防止连接被缓存(如果连接被缓存,用户名密码等所有信息都会被缓存) if (keepAlive) { AuthCacheValue.setAuthCache( new AuthCacheImpl()); } else { // 设置一个空的实现AuthCache可以防止用户名密码信息被缓存 AuthCacheValue.setAuthCache( new AuthCache() { public void remove(String pkey, AuthCacheValue entry) { } public void put(String pkey, AuthCacheValue value) { } public AuthCacheValue get(String pkey, String skey) { return null ; } }); } } |
在登录之前:
1
2
|
NetworkProxyTool.setKeepAliveAndAuthCache( false ); new .Login(); |
登录成功后:
1
|
NetworkProxyTool.setKeepAliveAndAuthCache( true ); |
6.保存用户的代理配置:
因为直接序列化自定义类型的对象,会存在版本问题(比如这个类的包名、类名改了,就死定了)。
所以不能直接序列化自定义类的对象,二是将自定义类对象的属性转成字典(Map),然后序列化map。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
/** * 读取本地网络代理设置配置文件 * * @return */ public static NetworkBean readNetworkBean() { NetworkBean networkBean = getCurrNetworkBean(readNetworkBeanMap()); if (networkBean == null ) { networkBean = new NetworkBean(); networkBean.setType(Proxy.Type.DIRECT); } return networkBean; } /** * 获取用户上次选择网络代理设置 * * @param map * @return */ public static NetworkBean getCurrNetworkBean(Map<String, Object> map) { putBrowserProxy(map); return (NetworkBean) map.get(getTypeMapKey(map)); } /** * 将浏览器的信息存放入代理信息总配置map * * @param map */ private static void putBrowserProxy(Map<String, Object> map) { if (browserProxyBean == null ) { browserProxyBean = getBrowserProxy(); } NetworkBean networkBeanBrowser = (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); } |
在登录之前:
1
2
3
4
|
NetworkBean networkBean = NetworkProxyTool.readNetworkBean(); NetworkProxyTool.setNetworkProxyBySystem(networkBean); NetworkProxyTool.setKeepAliveAndAuthCache( false ); new .Login(); |
在用户配置完代理点击确定时:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/** * 点击确定 */ private void confirm() { if ((isHttp() || isSocks()) && !checkIpAndPortNotNull()) { return ; } NetworkBean networkBean = 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); } else if (isSocks()) { // SOCKS代理 proxySettingMap.put(key_socks, networkBean); proxySettingMap.put(key_proxy_type, key_socks); } else if (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); } |
System Properties
Java System Properties网络设置有哪些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
Java System Properties优先级说明
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 都简单方便、统一。
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
NetworkBean httpBean = new NetworkBean(Proxy.Type.HTTP, "192.168.77.5" , "8888" , "tzc" , "123" , null ); Proxy httpProxy = new Proxy(httpBean.getType(), new InetSocketAddress(httpBean.getAddress(), Integer.parseInt(httpBean.getPort()))); NetworkBean socksBean = new NetworkBean(Proxy.Type.SOCKS, "192.168.77.5" , "9999" , "tzc" , "123" , "ttt" ); Proxy socksProxy = new Proxy(socksBean.getType(), new InetSocketAddress(socksBean.getAddress(), Integer.parseInt(socksBean.getPort()))); URLConnection httpProxyConnection = new URL( "http://www.baidu.com/" ).openConnection(httpProxy); //或者Authenticator.setDefault(new BairuiAuthenticator(networkBean.getDomainAndUsername(), networkBean.getPassword())); httpProxyConnection.setRequestProperty( "Proxy-Authorization" , "Basic " +httpBean.getDomainAndUsernameAndPassword64()); URLConnection socksProxyConnection = new URL( "http://www.baidu.com/" ).openConnection(socksProxy); //或者Authenticator.setDefault(new BairuiAuthenticator(networkBean.getDomainAndUsername(), networkBean.getPassword())); socksProxyConnection.setRequestProperty( "Proxy-Authorization" , "Basic " +httpBean.getDomainAndUsernameAndPassword64()); Socket socket = new Socket(socksProxy); Authenticator.setDefault( new BairuiAuthenticator(networkBean.getDomainAndUsername(), networkBean.getPassword())); socket.connect( new InetSocketAddress( "www.baidu.com" , 5555 )); |
总结
以上就是本文关于Java使用代理进行网络连接方法示例的全部内容,希望对大家学习Java有所帮助,欢迎各位浏览本站其他专题并随时留言,小编会及时回复大家的。
原文链接:http://blog.csdn.net/u012643122/article/details/53032482