Java使用代理進(jìn)行網(wǎng)絡(luò)連接方法示例
需求是這樣的:
一、界面上要有這樣幾種代理類(lèi)型可以選。
1.HTTP代理
2.Socks代理
3.不使用代理(直連)
4.使用瀏覽器設(shè)置(瀏覽器也是HTTP、Socks、直連三種)。
可參考QQ登錄設(shè)置里的代理能,其實(shí)跟qq的代理功能是一樣的。
二、測(cè)試使用所填寫(xiě)的代理配置信息是否可連接
三、記錄用戶(hù)上次選擇的代理配置,默認(rèn)使用用戶(hù)上次使用的代理配置進(jìn)行網(wǎng)絡(luò)連接。
程序運(yùn)行環(huán)境是WindowsXP、Windows7、Windows8系統(tǒng)。
使用的技術(shù)為Java7,Swing,CXF。
難點(diǎn):
1.如何進(jìn)行全居的代理設(shè)置:
/**
* 網(wǎng)絡(luò)代理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;// 代理類(lèi)型
private String address;// ip 地址
private String port;// 端口號(hào)
private String username;// 代理服務(wù)器用戶(hù)名
private String password;// 代理服務(wù)器用戶(hù)密碼
private String domain;// 域
private String typeText;// 代理類(lèi)型顯示的文本
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 + "]";
}
}
/**
* 根據(jù)指定的代理信息設(shè)置系統(tǒng)全局的網(wǎng)絡(luò)代理
*
* @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");
}
}
/**
* 網(wǎng)絡(luò)用戶(hù)名密碼校驗(yàn)提供者
*/
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使用系統(tǒng)的代理:
/**
* 為WebService接口添加網(wǎng)絡(luò)代理支持: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.使用瀏覽器設(shè)置:
/**
* 讀取用戶(hù)注冊(cè)表獲取瀏覽器的代理設(shè)置
*
* @return 該方法不會(huì)返回null值也不會(huì)拋出異常
*/
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\"";// 注冊(cè)表瀏覽器代理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) {// 從注冊(cè)表讀取失敗
e.printStackTrace();
}
return networkBean;
}
4.測(cè)試代理是否可用
因?yàn)槌绦蛑惺褂昧朔?wù)器的兩個(gè)不同的端口,所以需要測(cè)試兩個(gè)端口是否都可連。
如果使用了多臺(tái)服務(wù)器,更加需要分別測(cè)試了。
/**
* 測(cè)試網(wǎng)絡(luò)代理是否能通過(guò)連接,如果不通過(guò)拋出異常
*
* @throws Exception
*/
private static void testNetworkProxy() throws Exception {
testWebService();
testURLConnection();
}
/**
* 測(cè)試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對(duì)象讀取指定字符,如果不匹配則拋出異常
*
* @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固定返回這個(gè)字符串,如果service作了更改此處也應(yīng)更改
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;
}
}
/**
* 測(cè)試文件下載接口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);
}
/**
* 測(cè)試代理服務(wù)器連接
*/
private void testProxyConnection() {
NetworkBean readNetworkBean = NetworkProxyTool.readNetworkBean();// 先獲得正在使用的NetworkBean
try {
NetworkBean networkBean = createNetworkBean();// 根據(jù)用戶(hù)填寫(xiě)的信息創(chuàng)建的NetworkBean對(duì)象
showTestResultDialog(NetworkProxyTool.testNetworkProxyBySystem(networkBean));
} catch (Exception ex) {
showTestResultDialog(false);
}
NetworkProxyTool.setNetworkProxyBySystem(readNetworkBean);// 測(cè)試結(jié)束,還原原來(lái)的NetworkBean
}
5.因?yàn)閖ava連接網(wǎng)絡(luò)時(shí),如果使用當(dāng)前的代理連接失敗,那么就會(huì)使用操作系統(tǒng)中緩存的代理進(jìn)行網(wǎng)絡(luò)連接,如何是測(cè)試連接時(shí)不使用操作系統(tǒng)緩存,但測(cè)試結(jié)束后使用操作系統(tǒng)緩存。
/**
* 設(shè)置長(zhǎng)連接和驗(yàn)證信息緩存是否開(kāi)啟
*
* @param keepAlive
*/
public static void setKeepAliveAndAuthCache(boolean keepAlive) {
System.setProperty("http.keepAlive", keepAlive + "");// 設(shè)置是否開(kāi)始長(zhǎng)連接,如果為false可以防止連接被緩存(如果連接被緩存,用戶(hù)名密碼等所有信息都會(huì)被緩存)
if (keepAlive) {
AuthCacheValue.setAuthCache(new AuthCacheImpl());
} else {
// 設(shè)置一個(gè)空的實(shí)現(xiàn)AuthCache可以防止用戶(hù)名密碼信息被緩存
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;
}
});
}
}
在登錄之前:
NetworkProxyTool.setKeepAliveAndAuthCache(false); new.Login();
登錄成功后:
NetworkProxyTool.setKeepAliveAndAuthCache(true);
6.保存用戶(hù)的代理配置:
因?yàn)橹苯有蛄谢远x類(lèi)型的對(duì)象,會(huì)存在版本問(wèn)題(比如這個(gè)類(lèi)的包名、類(lèi)名改了,就死定了)。
所以不能直接序列化自定義類(lèi)的對(duì)象,二是將自定義類(lèi)對(duì)象的屬性轉(zhuǎn)成字典(Map),然后序列化map。
/**
* 讀取本地網(wǎng)絡(luò)代理設(shè)置配置文件
*
* @return
*/
public static NetworkBean readNetworkBean() {
NetworkBean networkBean = getCurrNetworkBean(readNetworkBeanMap());
if (networkBean == null) {
networkBean = new NetworkBean();
networkBean.setType(Proxy.Type.DIRECT);
}
return networkBean;
}
/**
* 獲取用戶(hù)上次選擇網(wǎng)絡(luò)代理設(shè)置
*
* @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);
}
在登錄之前:
NetworkBean networkBean = NetworkProxyTool.readNetworkBean(); NetworkProxyTool.setNetworkProxyBySystem(networkBean); NetworkProxyTool.setKeepAliveAndAuthCache(false); new.Login();
在用戶(hù)配置完代理點(diǎn)擊確定時(shí):
/**
* 點(diǎn)擊確定
*/
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網(wǎng)絡(luò)設(shè)置有哪些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優(yōu)先級(jí)說(shuō)明
host和port比set優(yōu)先級(jí)高,也就是說(shuō)set可以不用去設(shè)置。
如存在http.proxyHost和http.proxyPort時(shí),proxySet設(shè)為false無(wú)效,系統(tǒng)仍然可以使用http代理。
存在socksProxyHost和socksProxyPort時(shí),socksProxySet設(shè)為false無(wú)效,系統(tǒng)仍然可以使用socks代理。
http比socks優(yōu)先級(jí)高,即存在http.proxyHost和http.proxyPort時(shí),socksProxySet、socksProxyHost、socksProxyPort都會(huì)失效,系統(tǒng)會(huì)使用http代理。
使用java.net.Proxy
如果只是單個(gè)的連接需要使用代理,那么可以采用Proxy類(lèi)進(jìn)行代理連接。
說(shuō)明:
1.Socket只能使用socks代理不能使用http代理。
2.Socket使用使用Authenticator來(lái)進(jìn)行驗(yàn)證。
3.URLConnection 使用RequestProperty是只對(duì)當(dāng)前連接有效,不會(huì)緩存,Authenticator是全局性的,對(duì)所有網(wǎng)絡(luò)請(qǐng)求都有效,會(huì)緩存,但RequestProperty的優(yōu)先級(jí)比Authenticator高。
4.只有RequestProperty需要64位編碼,Authenticator不需要。
5.需要清除驗(yàn)證緩存的,不使用驗(yàn)證緩存上面已經(jīng)有代碼了,這里就不重復(fù)寫(xiě)了。
6.其實(shí),建議采用全局性的代理連接,不管是URLConnection 還是Socket 都簡(jiǎn)單方便、統(tǒng)一。
代碼:
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));
總結(jié)
以上就是本文關(guān)于Java使用代理進(jìn)行網(wǎng)絡(luò)連接方法示例的全部?jī)?nèi)容,希望對(duì)大家學(xué)習(xí)Java有所幫助,歡迎各位瀏覽本站其他專(zhuān)題并隨時(shí)留言,小編會(huì)及時(shí)回復(fù)大家的。
相關(guān)文章
JPA?通過(guò)Specification如何實(shí)現(xiàn)復(fù)雜查詢(xún)
這篇文章主要介紹了JPA?通過(guò)Specification如何實(shí)現(xiàn)復(fù)雜查詢(xún),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
基于Spring + Spring MVC + Mybatis 高性能web構(gòu)建實(shí)例詳解
這篇文章主要介紹了基于Spring + Spring MVC + Mybatis 高性能web構(gòu)建實(shí)例詳解,需要的朋友可以參考下2017-04-04
Java中對(duì)list元素進(jìn)行排序的方法詳解
這篇文章主要介紹了Java中對(duì)list元素進(jìn)行排序的方法詳解,是Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09
springboot實(shí)現(xiàn)對(duì)注解的切面案例
這篇文章主要介紹了springboot實(shí)現(xiàn)對(duì)注解的切面過(guò)程,首先定義一個(gè)注解、再編寫(xiě)對(duì)注解的切面只是記錄的執(zhí)行時(shí)間和打印方法,可以實(shí)現(xiàn)其他邏輯,需要的朋友可以參考一下2022-01-01
java-collection中的null,isEmpty用法
這篇文章主要介紹了java-collection中的null,isEmpty用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02

