java:解决URL.setURLStreamHandlerFactory只能被jvm调用一次的问题

如果你能找到这篇博客,你肯定是为实现URL协议扩展时自定义协议的StreamHandlerFactory注册问题而头痛。 一般而言,URL 的格式是: protocol://[authority]hostname:port/resource?queryString 常见协议头(protocol)有http,https,file。对应不同的协议,java都有提供默认URLStreamHandler对象来解析这些协议,如下图,这些位于rt.jar包中每一个package都对应一种协议,package下都有一个继承自URLStreamHandler的Handler类用于对应协议解析

如果要实现自己的协议,就需要自己写一个URLStreamHandler,如何写URLStreamHandler与具体项目需求相关,不是本文要讨论的重点。当我们想让自己写的URLStreamHandler生效,就需要将它注册到URL中,这篇文章《Java URL协议扩展实现》详细描述了两种机制,来实现URL协议扩展。 第一种方法就是用URL.setURLStreamHandlerFactory方法将自己的URLStreamHandlerFactory注册到URL类中。我打算采用的就是这种方式,因为这种方式相比jvm参数方式更加可控。 然而,根据URL.setURLStreamHandlerFactory方法的说明以及其代码可知,这个方法具有独占性,在JVM运行时只能被调用一次。(现在看来,这应该算是java的一个设计缺陷) 一般情况下,我们不一定能保证在自己调用URL.setURLStreamHandlerFactory时是第一次,所以调用很有可能失败。 怎么解决这个问题呢?Apache Commons Sandbox提供了一个解决方法,就是commons-jnet,它基本原理就是使用java reflect技术,强行改变URL中的私有成员变量factory(类型为URLStreamHandlerFactory)来保setURLStreamHandlerFactory能被成功调用,并且不破坏原有的factory。 common-jnet代码非常少,只有4个类,没有提供jar包,只是提供源码,从svn上checkout出来加入自己的项目代码就可以使用了

svn checkout http://svn.apache.org/repos/asf/commons/sandbox/jnet/trunk commons-jnet

具体的使用方式,common-jnet的官网上说明得非常明白也非常简单。 http://commons.apache.org/sandbox/commons-jnet/

找到common-jnet之前就发现org.eclipse.osgi中的EquinoxFactoryManager就是用相同的办法解决这个问题的,只是其中的代码混在一起不好摘出来。

参见 EquinoxFactoryManager.installURLStreamHandlerFactory方法和 EquinoxFactoryManager.forceURLStreamHandlerFactory方法的源码

参考资料:

《Java URL协议扩展实现》 apache.sandbox.commons-jnet

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AI研习社

嘀~正则表达式快速上手指南(下篇)

上面的代码中用 for 循环去遍历 contents 这样我们就可以一个一个处理每封邮件。我们创建一个字典, emails_dict,这将保存每个电子邮件的所有...

561
来自专栏用户2442861的专栏

java类加载过程

转载请注明出处:http://blog.csdn.net/ns_code/article/details/17881581

411
来自专栏小樱的经验随笔

【Java学习笔记之七】java函数的语法规则总结

函数的概述 发现不断进行加法运算,为了提高代码的复用性,就把该功能独立封装成一段独立的小程序,当下次需要执行加法运算的时候,就可以直接调用这个段小程序即可,那么...

3166
来自专栏用户2442861的专栏

【深入Java虚拟机】之四:类加载机制

转载请注明出处:http://blog.csdn.net/ns_code/article/details/17881581

441
来自专栏前端学习心得

JavaScript运行机制

1022
来自专栏Laoqi's Linux运维专列

python3–python模块+(复习)

3907
来自专栏专注数据中心高性能网络技术研发

[Effective Modern C++(11&14)]Chapter 3: Moving to Modern C++

2056
来自专栏专注 Java 基础分享

Java 的异常处理机制

902
来自专栏Java后端技术

这个坑,是时候填上了~

​  这两天,在网上逛的时候,发现了如下的一道面试题,感觉还有蛮有意思的,要是不仔细看还真容易掉到坑里面。第一眼看起来比较绕,所以比较难理解。最终我跳出了这个坑...

481
来自专栏超然的博客

前端相关片段整理——持续更新

在不同的接口请求数据然后拼合成自己所需的数据,通常这些接口之间没有关联(例如不需要前一个接口的数据作为后一个接口的参数)

761

扫码关注云+社区