在Java中,你可以使用相同的API但使用不同的URL协议加载各种资源:

file:///tmp.txt
http://127.0.0.1:8080/a.properties
jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class

这很好地将资源的实际加载与需要资源的应用程序分离开来,而且由于URL只是一个字符串,资源加载也非常容易配置。

是否存在使用当前类加载器加载资源的协议? 这与Jar协议类似,只是我不需要知道资源来自哪个Jar文件或类文件夹。

当然,我可以使用Class.getResourceAsStream(“a.xml”)做到这一点,但这需要我使用不同的API,因此需要对现有代码进行更改。我希望能够在所有可以为资源指定URL的地方使用它,只需更新属性文件即可。


当前回答

我不知道是否已经有了,但你可以很容易地自己做。

在我看来,不同协议的例子就像外观模式。当每种情况都有不同的实现时,您就有了一个公共接口。

您可以使用相同的原理,创建一个ResourceLoader类,它从属性文件中获取字符串,并检查我们的自定义协议

myprotocol:a.xml
myprotocol:file:///tmp.txt
myprotocol:http://127.0.0.1:8080/a.properties
myprotocol:jar:http://www.foo.com/bar/baz.jar!/COM/foo/Quux.class

从字符串开始剥离myprotocol,然后决定用哪种方式加载资源,只给你资源。

其他回答

再延伸一下Dilums的回答:

在不更改代码的情况下,您可能需要按照Dilum的建议,使用URL相关接口的自定义实现。为了简化事情,我建议查看Spring Framework的资源的源代码。虽然代码不是流处理程序的形式,但它的设计完全是为了做您想做的事情,并且是在ASL 2.0许可下进行的,这使得它足够友好,可以在您的代码中重用。

在Spring Boot应用程序中,我使用以下方法来获取文件URL,

Thread.currentThread().getContextClassLoader().getResource("PromotionalOfferIdServiceV2.wsdl")

我认为这是值得回答的问题——如果您正在使用Spring,那么您已经有了这个功能

Resource firstResource =
    context.getResource("http://www.google.fi/");
Resource anotherResource =
    context.getResource("classpath:some/resource/path/myTemplate.txt");

就像春季文档中解释的,斯卡夫曼在评论中指出的那样。

(类似于Azder的回答,但策略略有不同。)

我认为对于类路径中的内容没有预定义的协议处理程序。(所谓的类路径:协议)。

但是,Java允许您添加自己的协议。这是通过提供具体实现java.net.URLStreamHandler和java.net.URLConnection来实现的。

本文描述了如何实现自定义流处理程序: http://java.sun.com/developer/onlineTraining/protocolhandlers/。

我试图避免URL类,而是依赖URI。因此,对于需要URL的事情,我想做Spring资源查找,我做以下工作:

public static URL toURL(URI u, ClassLoader loader) throws MalformedURLException {
    if ("classpath".equals(u.getScheme())) {
        String path = u.getPath();
        if (path.startsWith("/")){
            path = path.substring("/".length());
        }
        return loader.getResource(path);
    }
    else if (u.getScheme() == null && u.getPath() != null) {
        //Assume that its a file.
        return new File(u.getPath()).toURI().toURL();
    }
    else {
        return u.toURL();
    }
}

要创建一个URI,可以使用URI.create(..)。这种方式也更好,因为您控制了将执行资源查找的ClassLoader。

我注意到其他一些答案试图将URL解析为字符串以检测该方案。我认为最好是传递URI并使用它来解析。

事实上,我在不久前提出了一个问题,要求Spring Source将他们的资源代码从核心中分离出来,这样你就不需要所有其他Spring的东西了。