如何正确使用ClassLoader.getResources()?

MRa*_*ser 78 java resources classpath classloader getresource

如何使用ClassLoader.getResources()从类路径中查找recursivly资源?

例如

  • 找到META-INF"目录" 中的所有资源:想象一下

    getClass().getClassLoader().getResources("META-INF")

    不幸的是,这只会检索URL到这个"目录".

  • 所有资源命名bla.xml(recursivly)

    getClass().getClassLoader().getResources("bla.xml")

    但是这会返回一个空的Enumeration.

并作为一个奖金问题:如何ClassLoader.getResources()区别ClassLoader.getResource()

rec*_*rec 35

Spring Framework有一个类,允许递归搜索类路径:

PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
resolver.getResources("classpath*:some/package/name/**/*.xml");
Run Code Online (Sandbox Code Playgroud)


kro*_*ock 20

无法以递归方式搜索类路径.您需要知道资源的完整路径名才能以这种方式检索它.资源可能位于文件系统的目录中或jar文件中,因此它不像执行"类路径"的目录列表那么简单.您需要提供资源的完整路径,例如'/com/mypath/bla.xml'.

对于第二个问题,getResource将返回与给定资源名称匹配的第一个资源.搜索类路径的顺序在getResource的javadoc中给出.

  • *没有办法递归搜索类路径*...当然,这是可能的.例如:`URLClassLoader.getURLs()`.打开JarFile,迭代. (12认同)
  • @bestsss,@ MRalwasser:或者更糟糕的是,如果它指向HTTP网址? (6认同)
  • @bestsss:如果URL没有指向JarFile,而是指向某个目录,该怎么办? (3认同)
  • ;)好吧,类加载器可以只是java.lang.ClassLoader的简单子类,无论如何都可以是URL部分.它可以在内存中生成类等.它可能有非常自定义的getResource等等@MRalwasser,如果它指向某个文件系统你就像那样处理它,这是一个简单的场景.@Joachim,除了applets,现在还没有远程保存文件的情况.URL可以是任何东西,但只要它是JAR一个,你就无法从http中检索jar .--我所说的并不总是这样,它并不像通用的解决方案那样,但它覆盖了超过98%的案例. (3认同)

Tom*_*ros 19

这是获取某个URL对象指向的File对象的最简单的wat:

File file=new File(url.toURI());
Run Code Online (Sandbox Code Playgroud)

现在,针对您的具体问题:

  • 查找META-INF"目录"中的所有资源:

您确实可以获取指向此URL的File对象

Enumeration<URL> en=getClass().getClassLoader().getResources("META-INF");
if (en.hasMoreElements()) {
    URL metaInf=en.nextElement();
    File fileMetaInf=new File(metaInf.toURI());

    File[] files=fileMetaInf.listFiles();
    //or 
    String[] filenames=fileMetaInf.list();
}
Run Code Online (Sandbox Code Playgroud)
  • 所有名为bla.xml的资源(recursivly)

在这种情况下,您将需要执行一些自定义代码.这是一个虚拟的例子:

final List<File> foundFiles=new ArrayList<File>();

FileFilter customFilter=new FileFilter() {
    @Override
    public boolean accept(File pathname) {

        if(pathname.isDirectory()) {
            pathname.listFiles(this);
        }
        if(pathname.getName().endsWith("bla.xml")) {
            foundFiles.add(pathname);
            return true;
        }
        return false;
    }

};      
//rootFolder here represents a File Object pointing the root forlder of your search 
rootFolder.listFiles(customFilter);
Run Code Online (Sandbox Code Playgroud)

运行代码时,您将在foundFilesList中获得所有找到的事件.

  • 我测试过,我得到一个异常:java.lang.IllegalArgumentException:URI不是分层的.您无法从像"jar:..."这样的不透明URI创建File对象 (25认同)
  • 我怀疑这适用于任何类型的ClassLoader(例如jar文件中的类) (10认同)

Mar*_*ler 9

这是基于bestsss答案的代码:

    Enumeration<URL> en = getClass().getClassLoader().getResources(
            "META-INF");
    List<String> profiles = new ArrayList<>();
    if (en.hasMoreElements()) {
        URL url = en.nextElement();
        JarURLConnection urlcon = (JarURLConnection) (url.openConnection());
        try (JarFile jar = urlcon.getJarFile();) {
            Enumeration<JarEntry> entries = jar.entries();
            while (entries.hasMoreElements()) {
                String entry = entries.nextElement().getName();
                System.out.println(entry);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 这种结构起初让我很困惑.似乎getClass().getClassLoader().getResources("META-INF")的唯一目的是获取对jar中某些任意文件的引用,然后我们使用它来获取JarURLConnection.我原本以为这会迭代META-INF目录中的文件,但它实际上遍历整个jar中的每个文件. (2认同)

bes*_*sss 5

MRalwasser,我会给你一个提示,施放URL.getConnection()JarURLConnection.然后使用JarURLConnection.getJarFile()并瞧!你有JarFile,你可以自由访问里面的资源.

其余的我留给你.

希望这可以帮助!