我正在使用带有嵌入式 Jetty 的可执行 jar 开发 Web 应用程序。
我的 jar 包含一个依赖的 jar。(jar in jar)
我引用了Eclipse开发的JarRsrcLoader
和RsrcURLStreamHandlerFactory
JarRsrcLoader
使用 URL#setURLStreamHandlerFactory(RsrcURLStreamHandlerFactory)
解析 rsrc
协议(protocol)。
从而它可以解析jar的类路径。
但是作为副作用,解决通常的协议(protocol)变得不可能。
例如 file:xxxx
或 jar:xxxx
。
RsrcURLStreamHandlerFactory
有 setURLStreamHandlerFactory
方法。
也许我认为我应该将默认实现设置为此方法。
我不知道是什么设置了这个方法。
最佳答案
URLStreamHandlerFactory
实现只有一个实例注册到 Java 运行时,因此该实现必须知道所有支持的协议(protocol)。
默认的 Oracle/Sun 行为不是以这种方式实现的,而是直接在 java.net.URL
类中实现的。因此,您不能简单地将默认实现作为链式工厂注入(inject)到 RsrcURLStreamHandlerFactory
中。答案的第一部分。
java.net.URL
getURLStreamHandler
方法根据其类名的命名策略加载协议(protocol) X
的实现,通过默认为 sun.net.www.protocol.X.Handler
如果您查看 jre/lib/rt.jar
,您会发现:
sun/net/www/protocol/ftp/Handler.class
sun/net/www/protocol/gopher/Handler.class
sun/net/www/protocol/mailto/Handler.class
sun/net/www/protocol/netdoc/Handler.class
sun/net/www/protocol/http/Handler.class
sun/net/www/protocol/jar/Handler.class
sun/net/www/protocol/file/Handler.class
用于协议(protocol) URLStreamHandler
选择的基础包列表来自 java.protocol.handler.pkgs
Java 系统属性。我邀请您阅读 JDK src.zip
中的 java/net/URL.java
的完整源代码以了解详细信息。
所以正确的方法(无论 IBM/Eclipse 做了什么)是保留默认机制并设置例如
-Djava.protocol.handler.pkgs="com.company.product .protocol"
在命令行上(如果您有这样做的许可/认证)。使用名为com.company.product.protocol.rsrc.Handler
并使用JarRsrcLoader
的URLStreamHandler
实现,您就可以完成工作。另一种选择是在
RsrcURLStreamHandlerFactory
中编写一个URLStreamHandlerFactory
实现作为链式工厂,灵感来自URL.getURLStreamHandler
源代码。例如,您可以阅读 this old JBoss code .它依赖于URL
内部处理程序缓存,方法是在注册工厂之前预加载其他已知(或使用)协议(protocol)。在我看来,只是丑陋。
警告:RsrcURLStreamHandler
已将 URLStreamHandler.parseURL
的原始 180 行代码替换为其自己的“10 行”版本"无需调用 super.parseURL
。当然它不遵守 URL 连接规范!请注意,您可能会遇到错误,具体取决于此类 URL 的使用方式。
关于java - URL.setURLStreamHandlerFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8938260/