Java 可执行 jar 找不到属性文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4126030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Executable jar won't find the properties files
提问by
I use this code in my program to load a properties file:
我在我的程序中使用此代码加载属性文件:
Properties properties = new Properties();
URL url = new App().getClass().getResource(PROPERTIES_FILE);
properties.load(url.openStream());
The code runs fine in Eclipse. Then I package the program into a JAR named MyProgram.jar, and run it, I got a NullPointerException at the second line. The JAR doesn't contain the properties file, they both are in the same directory. I am using Maven to create the JAR. How can I fix this problem?
代码在 Eclipse 中运行良好。然后我将程序打包到一个名为 MyProgram.jar 的 JAR 中,并运行它,我在第二行得到一个 NullPointerException。JAR 不包含属性文件,它们都在同一目录中。我正在使用 Maven 创建 JAR。我该如何解决这个问题?
UPDATE: I don't want to add the properties file to the JAR, since it will be created at deployment time.
更新:我不想将属性文件添加到 JAR,因为它将在部署时创建。
采纳答案by Pascal Thivent
BalusC is right, you need to instruct Maven to generate a MANIFEST.MF
with the current directory (.
) in the Class-Path:
entry.
BalusC 是对的,需要指示 Maven 生成一个MANIFEST.MF
带有当前目录 ( .
) 的Class-Path:
条目。
Assuming you're still using the Maven Assembly Plugin and the jar-with-dependencies
descriptor to build your executable JAR, you can tell the plugin to do so using the following:
假设您仍在使用 Maven 程序集插件和jar-with-dependencies
描述符来构建您的可执行 JAR,您可以使用以下命令告诉插件这样做:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.stackoverflow.App</mainClass>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path> <!-- HERE IS THE IMPORTANT BIT -->
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- append to the packaging phase. -->
<goals>
<goal>single</goal> <!-- goals == mojos -->
</goals>
</execution>
</executions>
</plugin>
回答by lscoughlin
EDIT: this is to respond to your comment:
编辑:这是为了回应您的评论:
You need to make sure that the properties file is on the class path with the right root for the java invocation that stars up the jar file. if your path is
您需要确保属性文件位于类路径上,并且具有启动 jar 文件的 java 调用的正确根。如果你的路径是
stuff/things.properties
东西/东西.properties
and the runtime location is
并且运行时位置是
/opt/myapp/etc/stuff/things.properties
/opt/myapp/etc/stuff/things.properties
and the jar file is in
并且jar文件在
/opt/myapp/bin/myjar
/opt/myapp/bin/myjar
then you need to launch as
那么你需要启动
/path/to/java -cp "/opt/myapp/etc:/opt/myapp/bin/myjar.jar" my.pkg.KavaMain
/path/to/java -cp "/opt/myapp/etc:/opt/myapp/bin/myjar.jar" my.pkg.KavaMain
working with this kind of config can be irksome in a dev environment, luckily, there's the maven exec pluginthat will get you the right kind of launch scenario.
在开发环境中使用这种配置可能会令人厌烦,幸运的是,maven exec 插件可以为您提供正确的启动场景。
Original Answer:
原答案:
You want to read about the maven resources plugin.
您想阅读有关Maven 资源插件的信息。
Basically you want to add something like this:
基本上你想添加这样的东西:
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*properties</include>
</includes>
</resource>
</resources>
</configuration>
<plugin>
to your pom.xml assuming that you're propertis file is with your java sources -- really it should be in src/main/resources.
到您的 pom.xml 假设您的属性文件与您的 java 源代码在一起——实际上它应该在 src/main/resources 中。
回答by BalusC
There are two workarounds:
有两种解决方法:
Don't use the JAR as executabele JAR, but as library.
java -cp .;filename.jar com.example.YourClassWithMain
Obtain the root location of the JAR file and get the properties file from it.
URL root = getClass().getProtectionDomain().getCodeSource().getLocation(); URL propertiesFile = new URL(root, "filename.properties"); Properties properties = new Properties(); properties.load(propertiesFile.openStream());
不要将 JAR 用作可执行文件 JAR,而是用作库。
java -cp .;filename.jar com.example.YourClassWithMain
获取 JAR 文件的根位置并从中获取属性文件。
URL root = getClass().getProtectionDomain().getCodeSource().getLocation(); URL propertiesFile = new URL(root, "filename.properties"); Properties properties = new Properties(); properties.load(propertiesFile.openStream());
None of both are recommended approaches! The recommend approach is to have the following entry in JAR's /META-INF/MANIFEST.MF
file:
两者都不是推荐的方法!推荐的方法是在 JAR/META-INF/MANIFEST.MF
文件中包含以下条目:
Class-Path: .
Then it'll be available as classpath resource the usual way. You'll really have to instruct Maven somehow to generate the MANIFEST.MF
file like that.
然后它将以通常的方式作为类路径资源可用。您真的必须以某种方式指示 Maven 生成这样的MANIFEST.MF
文件。
回答by Daniel F. Thornton
I had a similar problem, and this thread was a big help! FYI, I modified my Ant buildfile to do the MANIFEST-making, then designated that manifest when JAR-ing my server-side code:
我有一个类似的问题,这个线程是一个很大的帮助!仅供参考,我修改了我的 Ant 构建文件以进行清单制作,然后在 JAR 处理我的服务器端代码时指定该清单:
<!-- Create a custom MANIFEST.MF file, setting the classpath. -->
<delete file="${project.base.dir}/resources/MANIFEST.MF" failonerror="false"/>
<manifest file="${project.base.dir}/resources/MANIFEST.MF">
<attribute name="Class-Path" value="." />
</manifest>
<!-- JAR the server-side code, using the custom manifest from above. -->
<jar destfile="services/${name}.aar" manifest="${project.base.dir}/resources/MANIFEST.MF">
[....]
回答by Praveen Raj
thanks to all this code work out for me this url get our runnable jar location so easily i have to read my properties file so put your properties file in your runnable jar file location
感谢所有这些代码为我解决了这个 url 获取我们可运行的 jar 位置如此容易我必须读取我的属性文件所以将您的属性文件放在您的可运行 jar 文件位置
URL root = getClass().getProtectionDomain().getCodeSource().getLocation();
URL propertiesFile = new URL(root, "filename.properties");
Properties properties = new Properties();
properties.load(propertiesFile.openStream());