Java 可执行jar-won';找不到属性文件

Java 可执行jar-won';找不到属性文件,java,eclipse,jar,maven,Java,Eclipse,Jar,Maven,我在程序中使用以下代码加载属性文件: Properties properties = new Properties(); URL url = new App().getClass().getResource(PROPERTIES_FILE); properties.load(url.openStream()); 代码在Eclipse中运行良好。然后我将程序打包到一个名为MyProgram.JAR的JAR中,并运行它,在第二行得到一个NullPointerException。JAR不包含属性文件

我在程序中使用以下代码加载属性文件:

Properties properties = new Properties();
URL url = new App().getClass().getResource(PROPERTIES_FILE);
properties.load(url.openStream());
代码在Eclipse中运行良好。然后我将程序打包到一个名为MyProgram.JAR的JAR中,并运行它,在第二行得到一个NullPointerException。JAR不包含属性文件,它们都在同一个目录中。我正在使用Maven创建JAR。我如何解决这个问题


更新:我不想将属性文件添加到JAR中,因为它将在部署时创建。

编辑:这是对您的评论的回应:

您需要确保属性文件位于类路径上,具有启动jar文件的java调用的正确根。如果你的道路是

东西

并且运行时位置是

/opt/myapp/etc/stuff/things.properties

jar文件在

/opt/myapp/bin/myjar

然后你需要以

/path/to/java-cp”/opt/myapp/etc:/opt/myapp/bin/myjar.jar“my.pkg.KavaMain

在开发环境中使用这种配置可能会让人厌烦,幸运的是,有一种方法可以让您获得正确的启动场景

原始答复:

你想了解一下

基本上,您希望添加如下内容:

<plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
                <resources>
                        <resource>
                                <directory>src/main/java</directory>
                                <includes>
                                        <include>**/*properties</include>
                                </includes>
                        </resource>
                </resources>
        </configuration>
<plugin>

maven jar插件
src/main/java
**/*性质

假设您的propertis文件与java源代码在一起,那么它应该位于src/main/resources中。

有两种解决方法:

  • 不要将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());
    
  • 这两种方法都不是推荐的方法!推荐的方法是在JAR的
    /META-INF/MANIFEST.MF
    文件中包含以下条目:

    Class-Path: .
    

    然后,它将以通常的方式作为类路径资源提供。您必须以某种方式指示Maven生成这样的
    MANIFEST.MF
    文件。

    BalusC是对的,您需要指示Maven在
    类路径:
    条目中使用当前目录(
    )生成
    MANIFEST.MF

    假设您仍在使用Maven Assembly插件和带有依赖项的
    jar
    描述符来构建可执行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>
    
    
    maven汇编插件
    2.2
    带有依赖项的jar
    com.stackoverflow.App
    . 
    组装
    包裹
    单身
    
    我也遇到了类似的问题,这个帖子帮了大忙!仅供参考,我修改了我的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">
    [....]
    
    
    [....]
    
    感谢所有这些代码为我解决这个url获取我们可运行的jar位置 我必须很容易地读取属性文件,所以将属性文件放在可运行的jar文件位置

    URL root=getClass().getProtectionDomain().getCodeSource().getLocation();
    URL propertiesFile=新URL(根,“filename.properties”);
    属性=新属性();
    load(propertiesFile.openStream());
    
    旁注:既然您只是将其用作流,那么您使用
    getResource()
    而不是
    getResourceAsStream()
    有什么原因吗?没有,我没有任何特殊原因。您如何运行jar?如果通过java-jar,你能试试java-cp./MyProgram.jar,看看它是否有效吗?@Tomer:这是一种解决方法,不是解决方案。尽管如此,它还是不起作用。您没有在类路径中获取JAR的根文件夹。@Hai:为什么要删除
    maven
    标记?你评论了我的回答“你知道如何通过maven添加它吗?”。所以你使用maven,因为它做的事情不同,最终的答案取决于这一点。我不知道怎么做,所以我删除了答案并重新标记了问题,以提高出席率。Maven是唯一能够可靠地回答这个问题的人。谢谢,但我不想将属性文件添加到JAR中。它将在部署时更改。根据您的编辑:使用
    -jar
    参数时忽略
    -cp
    参数。它必须进入
    MANIFEST.MF
    文件:)@BalusC righto,修正了。如果MANIFEST.MF可以在运行时移动,则无法进入该MANIFEST.MF。逗号filename.jar。也许这就是它不起作用的原因。感谢您的帮助。避免使用类路径有一个原因,即如果在读取之间内容发生变化。资源加载器缓存第一个内容如果您没有使用maven assembly插件,请告诉我,我会更新我的答案。使用
    执行
    部分,我不必单独运行
    mvn assembly:assembly
    ,对吗?顺便说一句,谢谢你回答我关于Maven的所有问题。@HaiMinhNguyen:事实上,上述
    执行
    阶段绑定了
    单个
    目标。因此,运行
    mvn包
    确实会创建程序集。哦,不客气。是的,这是您应该采取的方法,Hai Minh Nguyen。您好,我尝试使用上述方法创建一个具有依赖项的jar,它可以加载位于同一目录中的属性文件,但不起作用。我使用“java-jarmyjar.jar”运行我的jar。我尝试使用Class.getResource()Class.ClassLoader.getResource()和Class.getResource()检索属性文件,在文件名中使用或不使用前导斜杠,但这些都不起作用。如果我打印java.class.path的内容,我只会得到我的jar文件(不是“.”