加载包含在一个罐子里


21

在我的应用程序以这种方式加载资源的资源:

WinProcessor.class.getResource("repository").toString(); 

,这给了我:

file:/root/app/repository (and I replace "file:" with empty string) 

,当我从IDE运行我的应用程序也能正常工作,但是当我运行我的应用程序的罐子:

java -jar app.jar 

的路径变为:

jar:/root/app.jar!/repository 

有没有什么办法可以解决这个问题?

我会为了创建这个使用“仓库”目录名称:

ConfigurationContext ctx = (ConfigurationContext) ConfigurationContextFactory.createConfigurationContextFromFileSystem(repositoryString, null); 

以同样的方式,我会得到一个文件名(而不是目录),我将使用它是这样的:

System.setProperty("javax.net.ssl.trustStore", fileNameString) 
35

听起来好像你正试图加载资源使用FileInputStream或类似的东西。不要这样做:不要拨打getResource,请拨打getResourceAsStream并从中读取数据。

(你可以加载从网址,而不是资源,但调用getResourceAsStream更方便一点。)

编辑:在看到更新后的答案,似乎其他代码位依赖于一个数据是文件系统中的物理单个文件。因此,答案不是首先将它捆绑在一个jar文件中。你可能检查它是否在一个单独的文件,如果不提取它到一个临时文件,但这是相当hacky IMO。

+1

同意。每当你不能100%肯定地说你会处理物理单个文件(java web start for one)时,你应该总是用流编码。 22 2月. 092009-02-22 12:16:38


5

构建一个URL,那么你可以加载资源(即使是在一个jar文件)使用openStream方法。

+1

这就是'getResourceAsStream'所做的。 12 7月. 162016-07-12 14:20:56


9

当使用java -jar app.jar运行代码时,java仅使用JAR文件清单中定义的类路径(即Class-Path属性)。如果该类在app.jar中,或者该类在JAR清单的Class-Path属性中设置的类路径中,则可以使用以下代码片段加载该类,其中className是完全限定的类名。

final String classAsPath = className.replace('.', '/') + ".class"; 
final InputStream input = ClassLoader.getSystemResourceAsStream(path/to/class); 

现在,如果类不是JAR的一部分,它是不是在清单的Class-Path,那么类装载器将无法找到它。相反,你可以使用URLClassLoader,小心处理windows和Unix/Linux/MacOSX之间的差异。

// the class to load 
final String classAsPath = className.replace('.', '/') + ".class"; 

// the URL to the `app.jar` file (Windows and Unix/Linux/MacOSX below) 
final URL url = new URL("file", null, "///C:/Users/diffusive/app.jar"); 
//final URL url = new URL("file", null, "/Users/diffusive/app.jar"); 

// create the class loader with the JAR file 
final URLClassLoader urlClassLoader = new URLClassLoader(new URL[] { url }); 

// grab the resource, through, this time from the `URLClassLoader` object 
// rather than from the `ClassLoader` class 
final InputStream input = urlClassLoader.getResourceAsStream(classAsPath); 

在你需要处理异常两个例子,而事实上,输入流是null如果资源不能被发现。另外,如果您需要将InputStream转换为byte[],则可以使用Apache的公共区域IOUtils.toByteArray(...)。而且,如果您想要Class,则可以使用类加载程序的defineClass(...)方法,该方法接受byte[]

您可以在扩散源代码,你可以在github.com/robphilipp/diffusive

和一种方法找到SourceForge上为Windows和Unix/Linux创建URL找到一个ClassLoaderUtils类的代码/从相对和绝对路径的MacOSX RestfulDiffuserManagerResource.createJarClassPath(...)