Java自定义URL协议

        Java 提供了对 URL 协议进行扩展的能力,通过扩展用户可以自定义 URL 通信协议, JDK 默认提供了对 HTTP,FTP,JAR,FILE 等的实现,而当需要自己定义通信协议的时候,就需要利用 JDK 提供的对 URL 扩展机制进行自定义。

         JDK 主要提供了如下三种方式对 URL 进行扩展,每种方式都有各自的使用场景,下面我们分别看看具体 JDK 都给我们提供了哪些扩展点。

1.         实现 URLStreamHandlerFactory 接口,然后调用 URL.setURLStreamHandlerFactory.

采用这种方式的情况下,需要确保应用的其他地方没有调用 setURLStreamHandlerFactory ,因为此方法只能调用一次,如果多次调用会抛出 java.lang.Error: factory already defined. 比如在一些应用服务器的中使用的时候就要多加注意。

 

2.         创建 URLStreamHandler 的子类,这种方式必须满足如下两个约定:

a)         子类的类名必须是 Handler ,同时最后一级的包名必须是协议的名称,比如你自己定义了名为 mem 的协议,那么 handler 的全名不须是 com.company.protocol.Handler.

b)         JVM 启动的时候,需要设置 java.protocol.handler.pkgs 系统属性,如果有多个实现类,那么中间用 | 隔开。

 

上面两个约定我们可以通过查看 JDK 中的 URL 的源代码,可以清晰的看到为什么要遵循这两个约定。下面我们就看一下 JDK 中关于 URL 的源代码。

static URLStreamHandler getURLStreamHandler(String protocol) {
		  …… ……   
            
            if (handler == null) {
           	 //这里获取java.protocol.handler.pkgs系统属性,同时用“|”隔开 
                String packagePrefixList = null;
                packagePrefixList
                    = (String) java.security.AccessController.doPrivileged(
                    new sun.security.action.GetPropertyAction(
                        protocolPathProp, ""));
                if (packagePrefixList != "") {
                    packagePrefixList += "|";
                }

                // REMIND: decide whether to allow the "null" class prefix
                // or not.
                packagePrefixList += "sun.net.www.protocol";
			
                
                StringTokenizer packagePrefixIter =
                    new StringTokenizer(packagePrefixList, "|");

                while (handler == null &&
                    packagePrefixIter.hasMoreTokens()) {

                    String packagePrefix =
                        packagePrefixIter.nextToken().trim();
                    try {
					//这里packagePrefix就是你自己制定的包名,protocol为你自定义的协议名,这
                        String clsName = packagePrefix + "." + protocol +
                            ".Handler";
                        Class cls = null;
                        try {
                            cls = Class.forName(clsName);// 用加载URL的类加载器加载
                        } catch (ClassNotFoundException e) {
                            ClassLoader cl = ClassLoader.getSystemClassLoader(); //采用系统类加载器加载
                            if (cl != null) {
                                cls = cl.loadClass(clsName);
                            }
                        }
                        if (cls != null) {
                            handler =
                                (URLStreamHandler) cls.newInstance();
                        }
                    } catch (Exception e) {
                        // any number of exceptions can get thrown here
                    }
                }
            }
        }
}

当采用这种方法的时候,需要注意的是自己写的 Handler 类必须放在系统类加载器可以加载到的地方。

 

3   实例化一个 URL 对象的时候传递一个 URLStreamHandler 的实例。这种方式的情况下, JDK 需要一个名为 specifyStreamHandlerNetPermission ,这就要求你需要去修改 jdk 安装目录下的 java.policy 文件进行授权。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值