java url 协议_Java自定义URL协议

本文介绍了Java如何扩展URL协议,包括实现URLStreamHandlerFactory接口、创建URLStreamHandler子类和在实例化URL对象时传入URLStreamHandler。详细讲解了每种方式的使用场景和注意事项,特别强调了JVM启动时设置java.protocol.handler.pkgs系统属性的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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的源代码。

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

}

}

}

}

}

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需要一个名为specifyStreamHandler的NetPermission,这就要求你需要去修改jdk安装目录下的java.policy文件进行授权。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值