我有一个I18n
帮助程序类,可以通过查看应用程序Jar中文件的名称来查找可用的Locale
。
private static void addLocalesFromJar(List<Locale> locales) throws IOException {
ProtectionDomain domain = I18n.class.getProtectionDomain();
CodeSource src = domain.getCodeSource();
URL url = src.getLocation();
JarInputStream jar = new JarInputStream(url.openStream());
while (true) {
JarEntry entry = jar.getNextJarEntry();
if (entry == null) {
break;
}
String name = entry.getName();
// ...
}
}
目前,这不起作用 - jar.getNextJarEntry()
似乎总是返回null
。我不知道为什么会发生这种情况,我所知道的是url
设置为rsrc:./
。我从未见过该协议,也找不到任何相关内容。
奇怪的是,这有效:
class Main {
public static void main(String[] args) {
URL url = Main.class.getProtectionDomain().getCodeSource().getLocation();
JarInputStream jar = new JarInputStream(url.openStream());
while (true) {
JarEntry entry = jar.getNextJarEntry();
if (entry == null) {
break;
}
System.out.println(entry.getName());
}
}
}
在这个版本中,即使它们之间几乎没有区别,url
也正确设置为Jar文件的路径。
为什么第一个版本不起作用,是什么打破了它?
更新:
工作示例实际上只有在我不使用Eclipse导出它时才有效。它在NetBeans中运行得很好,但在Eclipse版本中,URL也设置为rsrc:./
。
由于我使用Package required libraries into generated JAR
库处理导出它,Eclipse将其jarinjarloader
放入我的Jar中,因此我可以在其中包含所有依赖项。它可以与其他设置一起使用,但有没有办法让它独立于它们工作?
目前,该类是我的应用程序的一部分,但我打算将它放在一个单独的库中。在这种情况下,我如何确保它可以使用单独的Jars?
答案 0 :(得分:2)
问题是Eclipse正在使用的jarinjarloader ClassLoader。显然它使用自己的自定义rsrc:URL方案指向存储在主jar文件中的jar文件。您的URL流处理程序工厂无法理解此方案,因此openStream()方法返回null,这会导致您遇到的问题。
这回答了关于单独罐子的问题的第二部分 - 这不仅会起作用,而且它是唯一有效的方法。您需要更改主应用程序以使用单独的jar而不是将它们全部捆绑在主jar中。如果您正在构建Web应用程序,请将它们复制到WEB-INF / lib目录中,您就可以了。如果您正在构建桌面应用程序,请将META-INF / MANIFEST.MF中的相对路径引用添加到其他jar中,当您运行主jar时,它们将自动作为类路径的一部分包含在内。
答案 1 :(得分:1)
代码可能会也可能不会导致I18n所在的jar文件。 getProtectionDomain也可以为null。这取决于类加载器的实现方式。
ProtectionDomain domain = I18n.class.getProtectionDomain();
CodeSource src = domain.getCodeSource();
URL url = src.getLocation();
关于rsrc:./
协议,类加载器可以自由使用他们喜欢的任何URL(或者为此命名)
试试这个,你可能会很幸运:)
URL url = getClass().getResource(getClass().getSimpleName()+".class");
java.net.JarURLConnection conn = (java.net.JarURLConnection) url.openConnection();
Enumeration<JarEntry> e = conn.getJarFile().entries();
...
祝你好运!
答案 2 :(得分:1)
Eclipse的jarinjarloader使用系统类加载器加载所有内容,它永远不知道从哪个jar文件加载。这就是为什么你无法获得rsrc:
网址的jar网址。
我建议将语言环境列表存储在每个应用程序jar中的文件中,例如: META-INF/locales
。然后,您可以使用ClassLoader.getResources("META-INF/locales")
获取类路径中具有该名称的所有文件的列表,并将它们组合以获取完整的语言环境列表。
答案 3 :(得分:0)
我使用System.getProperty(“java.class.path”)来获取jar的位置。我不知道这是否有所作为。我没有探索过ProtectDomain路径,所以我无法帮助你,抱歉。至于多个罐子,也只是遍历那些jar文件。