介绍和基本实现
首先,您至少需要一个URLStreamHandler。这实际上会打开到给定URL的连接。注意,这被简单地称为Handler;这允许你指定java -Djava.protocol.handler.pkgs=org.my。协议,它将自动被拾取,使用“简单”包名作为支持的协议(在本例中为“classpath”)。
使用
new URL("classpath:org/my/package/resource.extension").openConnection();
Code
package org.my.protocols.classpath;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
/** A {@link URLStreamHandler} that handles resources on the classpath. */
public class Handler extends URLStreamHandler {
/** The classloader to find resources from. */
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 Handler注册
最终的选择是注册一个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()。然后像第一个例子那样输入新的URL("classpath:org/my/package/resource.extension"),然后就可以继续了。
JVM处理器注册问题
请注意,每个JVM只能调用该方法一次,并且请注意Tomcat将使用此方法注册JNDI处理程序(AFAIK)。试试Jetty(我会的);在最坏的情况下,您可以先使用方法,然后它必须在您周围工作!
许可证
我将此发布到公共领域,并询问如果您希望修改,您将在某处启动OSS项目并在这里评论详细信息。一个更好的实现是有一个URLStreamHandlerFactory,它使用ThreadLocals来存储每个Thread.currentThread(). getcontextclassloader()的URLStreamHandlers。我甚至会给你我的修改和测试课程。