文档章节

记录一下几年前开发的Java网络代理功能

思想永无止境
 思想永无止境
发布于 2016/11/04 11:59
字数 1681
阅读 7
收藏 0

需求是这样的:

一、界面上要有这样几种代理类型可以选。
1.HTTP代理
2.Socks代理
3.不使用代理(直连)
4.使用浏览器设置(浏览器也是HTTP、Socks、直连三种)

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

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

程序运行环境是WindowsXP、Windows7、Windows8系统。
使用的技术为Java7,Swing,CXF。

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

/** * 网络代理Bean * * @author tang * @date 2014/11/4 */
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);
    }

© 著作权归作者所有

思想永无止境
粉丝 4
博文 257
码字总数 292814
作品 0
昌平
程序员
私信 提问
关于jdk1.6的instrumentation代理使用问题

Java SE 6 的新特性:虚拟机启动后的动态 instrument 在 Java SE 5 当中,开发者只能在 premain 当中施展想象力,所作的 Instrumentation 也仅限与 main 函数执行前,这样的方式存在一定的局...

关键词
2014/03/12
246
0
php+access实现limit查询

虽然切版一直致力于为网站建设公司提供优质的web前端外包开发服务,但是我们也是懂程序的,这一点鲜有人知道,只是我们放弃了二流的程序技术,更愿意把一流的前端开发技术服务更多的人群,关...

切版
2017/11/15
43
0
淘宝Tprofiler工具实现分析

项目首页:https://github.com/alibaba/TProfiler 工具介绍 TProfiler是一个可以在生产环境长期使用的性能分析工具.它同时支持剖析和采样两种方式,记录方法执行的时间和次数,生成方法热点 对...

伍咖
2015/11/14
269
0
Java之父公开亮相 称Oracle掌管Java令人放心

美国时间3月17日,在Oracle收购Sun Microsystems之后,Java之父James Gosling首度在公开场合露面,他一如既往保持着对Java的高度关注,并表示Java在Oracle的掌管下令人放心,随后他还透露了J...

红薯
2010/03/20
654
4
程序员到架构师要学习那些东西?一般要几年?

我是97年出生的,上初中的时候受马云,李彦宏,周鸿祎,李想,李兴平的影响,我对Web比较喜欢。最后我中考完后选择 了一家培训机构 ,主要培训Java,.net。今年刚毕业11月来的上海,找到了一...

1111115454
2015/01/03
4.7K
15

没有更多内容

加载失败,请刷新页面

加载更多

parseint和isNaN用法

本文转载于:专业的前端网站➭parseint和isNaN用法 <!doctype html><html><head><meta charset="utf-8"><title>无标题文档</title></head><body><script> var a='12'; alert......

前端老手
39分钟前
7
0
Kylin 精确去重在用户行为分析中的妙用

作者:史少锋,Apache Kylin committer & PMC,2019/10/11 在上次文章《如何在 1 秒内做到大数据精准去重》中,我们介绍了 Apache Kylin 为什么要支持大数据集上的精确去重,以及基于 Bitmap...

ApacheKylin
50分钟前
5
0
学习记录(二) es6基本语法(rest参数,模板化,axios模块,拦截器)

日常学习记录 模块化:把一个大文件分成多个小文件,按照一定规范进行拼接 es5写法: 导出:module.exports = 数据 导入:require("路径") /路径未添加后缀名时 //默认添加.js //把路径作为文件名...

Pole丶逐
54分钟前
4
0
以程序员的角度怎么购买一台「性价比高的电视」

前俩天有小伙伴在我的文章下留言,说能否把 【国内电视机都介绍一下】,今天我已在TV端开发多年的程序员的角度。谈谈已程序员的角度如何购买一台性价比高的电视。 国内大的电视机品牌介绍 长...

我们都很努力着
57分钟前
4
0
PhotoShop 色调:理解直方图/RGB通道信息

一、直方图:图表的形式,展示图像像素分布的情况 1.平均值:表示平均亮度 2.标准偏差值:表示亮度值范围内的中间值 3.像素: 表示用于计算直方图的像素总数 4.色阶:显示指针下面的区域亮度...

东方墨天
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部