如何访问jar中的资源,它可以存在于多个jar中

时间:2010-10-25 18:45:05

标签: java jar

我有一个项目,我会针对许多XSD生成大量代码。为了使事物分离,每组XSD在项目中捆绑在一起。我有多个项目,它将在资源中看到XSD并生成针对它们的代码。

我的问题是当我尝试访问存储在jar文件中的XSD时,我无法从特定的jar中获取访问XSD的代码。相反,无论jar如何,它都将访问与标准匹配的第一个XSD。

以下是我用来列出资源的代码,所有的jar都具有相同的结构,这意味着XSD总是存储在jar文件根目录的xsd文件夹中。下面的代码列出了文件夹中的XSD。

URL dirURL = clazz.getClassLoader().getResource(path);
  System.out.println(dirURL.toURI());
  if (dirURL != null && dirURL.getProtocol().equals("file")) {
   /* A file path: easy enough */
   System.out.println(dirURL.toURI());
  return new File(dirURL.toURI()).list();
  }

  if (dirURL == null) {
   /* 
    * In case of a jar file, we can't actually find a directory.
    * Have to assume the same jar as clazz.
    */
   String me = clazz.getName().replace(".", "/") + ".class";
   dirURL = clazz.getClassLoader().getResource(me);
   System.out.println(dirURL.toURI());
   System.out.println(me);
  }

  if (dirURL.getProtocol().equals("jar")) {
   /* A JAR path */
   String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
   System.out.println(jarPath);
   JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
   Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
   Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
   String name = null;
   while (entries.hasMoreElements()) {
    name = entries.nextElement().getName();
    if (name.startsWith(path)) { //filter according to the path
     String entry = name.substring(path.length());
     int checkSubdir = entry.indexOf("/");
     if (checkSubdir >= 0) {
      // if it is a subdirectory, we just return the directory name
      entry = entry.substring(0, checkSubdir);
     }
     result.add(entry);
    }
   }
   return result.toArray(new String[result.size()]);

2 个答案:

答案 0 :(得分:2)

我通常会规定将资源目录添加到每个JAR中,并使用对其下保存的JAR唯一的资源。例如(在Maven结构中)

module1/src/main/resources/module1/example.xsd
module2/src/main/resources/module2/example.xsd

然后使用

引用XSD
InputStream module1XSD= SomeClass.class.getResourceAsStream("/module1/example.xsd");
InputStream module2XSD= SomeClass.class.getResourceAsStream("/module2/example.xsd");

只要module1和module2的JAR放在包含SomeClass的应用程序的类路径上。

Spring上下文会将这些引用为

classpath:module1/example.xsd,
classpath:module2/example.xsd

这意味着您必须能够在您生成的JAR中移动XSD的位置。甚至可能通过构建脚本重新生成它们。

答案 1 :(得分:1)

如果XSD都具有相同的名称,您将需要另一个标准,知道“正确的”是什么。您是否可以在其中嵌入一些信息(或者使用它,如属性文件或其他东西)来表明其目的?

而且,获取它们的更方便的迭代器可能是:

 getClass().getClassLoader().getResources("/file.xsd");

或者其他什么。 (依赖于类路径,无论是在文件系统上还是在jar中)