介绍和基本实现
首先,您至少需要一个URLStreamHandler。 这将实际打开到给定URL的连接。 请注意,它简单地称为Handler
;这允许您指定java -Djava.protocol.handler.pkgs=org.my.protocols
,并且它将自动被拾取,使用“simple”包名称作为支持的协议(在此例中是“classpath”)。
用法
new URL("classpath:org/my/package/resource.extension").openConnection();
代码
package org.my.protocols.classpath;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
public class Handler extends URLStreamHandler {
private final ClassLoader classLoader;
public Handler() {
this.classLoader = getClass().getClassLoader();
}
public Handler(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
protected URLConnection openConnection(URL u) throws IOException {
final URL resourceUrl = classLoader.getResource(u.getPath());
return resourceUrl.openConnection();
}
}
启动问题
如果你和我一样,不想依赖于在启动时设置属性来让你到达某个地方(在我这种情况下,我喜欢保持我的选择开放,比如Java WebStart - 这就是为什么
我需要所有这些)。
解决方法/增强功能
手动代码处理程序规范
如果你掌控着代码,你可以做:
new URL(null, "classpath:some/package/resource.extension", new org.my.protocols.classpath.Handler(ClassLoader.getSystemClassLoader()))
这将使用您的处理程序打开连接。
但是,这还不够令人满意,因为您不需要URL来执行此操作 - 您想要这样做是因为某个库希望使用URL,而您无法或不想控制...
JVM处理程序注册
最终选项是注册一个URLStreamHandlerFactory
,它将处理JVM中的所有URL:
package my.org.url;
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import java.util.HashMap;
import java.util.Map;
class ConfigurableStreamHandlerFactory implements URLStreamHandlerFactory {
private final Map<String, URLStreamHandler> protocolHandlers;
public ConfigurableStreamHandlerFactory(String protocol, URLStreamHandler urlHandler) {
protocolHandlers = new HashMap<String, URLStreamHandler>();
addHandler(protocol, urlHandler);
}
public void addHandler(String protocol, URLStreamHandler urlHandler) {
protocolHandlers.put(protocol, urlHandler);
}
public URLStreamHandler createURLStreamHandler(String protocol) {
return protocolHandlers.get(protocol);
}
}
要注册处理程序,请使用配置的工厂调用URL.setURLStreamHandlerFactory()
。然后像第一个示例一样执行new URL("classpath:org/my/package/resource.extension")
,就可以开始了。
JVM处理程序注册问题
请注意,每个JVM只能调用此方法一次,并且请注意Tomcat将使用此方法注册JNDI处理程序(AFAIK)。尝试Jetty(我会尝试);在最坏的情况下,您可以先使用该方法,然后它必须围绕您工作!
许可证
我将其发布到公共领域,并要求如果您希望进行修改,请在某处启动OSS项目并在此处注释详细信息。更好的实现是具有URLStreamHandlerFactory
的线程本地存储URLStreamHandler
,以存储每个Thread.currentThread().getContextClassLoader()
的处理程序。我甚至会提供我的修改和测试类。
com.github.fommil.common-utils
包的一部分,计划通过 Sonatype 进行更新和发布。 - fommilSystem.setProperty()
来注册协议。例如:System.setProperty("java.protocol.handler.pkgs", "org.my.protocols");
- tsauerwein