当前位置: 移动技术网 > IT编程>开发语言>Java > Java使用代理进行网络连接方法示例

Java使用代理进行网络连接方法示例

2019年07月19日  | 移动技术网IT编程  | 我要评论

需求是这样的:

一、界面上要有这样几种代理类型可以选。

1.http代理

2.socks代理

3.不使用代理(直连)

4.使用浏览器设置(浏览器也是http、socks、直连三种)。

可参考qq登录设置里的代理能,其实跟qq的代理功能是一样的。

二、测试使用所填写的代理配置信息是否可连接

三、记录用户上次选择的代理配置,默认使用用户上次使用的代理配置进行网络连接。

程序运行环境是windowsxp、windows7、windows8系统。

使用的技术为java7,swing,cxf。

难点:

1.如何进行全居的代理设置:

/**
 * 网络代理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 + "]";
  }
}
/**
   * 根据指定的代理信息设置系统全局的网络代理
   * 
   * @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使用系统的代理:

 /**
   * 为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.使用浏览器设置:

/**
   * 读取用户注册表获取浏览器的代理设置
   * 
   * @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.测试代理是否可用

因为程序中使用了服务器的两个不同的端口,所以需要测试两个端口是否都可连。

如果使用了多台服务器,更加需要分别测试了。

 /**
   * 测试网络代理是否能通过连接,如果不通过抛出异常
   * 
   * @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);
  }
 /**
   * 测试代理服务器连接
   */
  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连接网络时,如果使用当前的代理连接失败,那么就会使用操作系统中缓存的代理进行网络连接,如何是测试连接时不使用操作系统缓存,但测试结束后使用操作系统缓存。

 /**
   * 设置长连接和验证信息缓存是否开启
   * 
   * @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;
        }
      });
    }
  }

在登录之前:

  networkproxytool.setkeepaliveandauthcache(false);
  new.login();

登录成功后:

 networkproxytool.setkeepaliveandauthcache(true);

6.保存用户的代理配置:

因为直接序列化自定义类型的对象,会存在版本问题(比如这个类的包名、类名改了,就死定了)。
所以不能直接序列化自定义类的对象,二是将自定义类对象的属性转成字典(map),然后序列化map。

/**
   * 读取本地网络代理设置配置文件
   * 
   * @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);
  }

在登录之前:

  networkbean networkbean = networkproxytool.readnetworkbean();
  networkproxytool.setnetworkproxybysystem(networkbean);
  networkproxytool.setkeepaliveandauthcache(false);
  new.login();

在用户配置完代理点击确定时:

 /**
   * 点击确定
   */
  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



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 都简单方便、统一。

代码:

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有所帮助,欢迎各位浏览本站其他专题并随时留言,小编会及时回复大家的。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网