Maven和Eclipse:在maven库项目中加载默认属性并在runnable Jar中使用它

Rob*_*ans 11 java eclipse jar properties maven

我相信在stackoverflow之前已经问过这个问题.我想提一下,我尝试了与我相关的问题所带来的解决方案.最接近我的问题的是: 在JAR中加载属性文件?.
可悲的是,那里描述的解决方案对我不起作用.由于问题的年龄,我想再问一遍是要走的路.

继续描述我的问题.
所以目前我正在开发一个已经使用maven设置的库项目,并为当前的Spring AMQP项目创建了一个扩展.
这里的目标是提供一个JAR文件,该文件可以包含在另一个项目中,以支持通过消息代理进行通信的特定方式.
此时,我正在实现配置选项,以允许用户根据自己的喜好配置消息传递客户端.但是当我测试这个功能的功能时,我在可执行的JAR中使用库时遇到了问题.

在Eclipse工作区中运行它时,一切似乎都运行得很好.但是当我尝试从我的桌面运行它(作为一个可运行的JAR)时,似乎找不到任何属性文件.

只是为了快速概述上面描述的工作空间/项目设置: 工作区概述

两个项目的项目结构都反映了Maven默认的一个:

- src/main/java
    - java source files
- src/main/resources
    - resource files
- src/test/java
    - java test files
- src/test/resources
    - test resource files
Run Code Online (Sandbox Code Playgroud)

库文件在src/main/resources文件夹中包含default.properties文件,而chatclient项目包含custom.properties文件.

一旦构建了可运行的JAR文件,它就具有以下结构.

- com
- junit
- META-INF
- org
- resources
    - default.resources
    - custom.resources
Run Code Online (Sandbox Code Playgroud)

我相信资源文件不应该位于那里.但在META-INF/maven文件夹中.尝试过这样的东西之后:

  • 将META-INF文件夹添加到我的src/main/resources文件夹中并将属性文件放在那里.
  • 使用Class-Path添加MANIFEST文件:.在里面.
  • 在代码中以多种方式加载文件.

但似乎没有任何效果.我猜这是Maven相关的,并且pom.xml中的一个简单更改可以修复它.遗憾的是,我对Maven项目设置和pom相关主题的了解非常基础(这是我使用maven的第一个项目).我似乎无法找到任何文件,即使我知道它应该在那里(可能是由我引起的问题).

在我忘记提及之前.我使用这种方式加载属性文件:

Properties props = new Properties();
prop.load(<custom static class>.class.getResourceAsStream(filename));
return props;
Run Code Online (Sandbox Code Playgroud)

我的库的pom.xml看起来像:

-- Artifact stuff --
<packaging>jar</packaging>
<build>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
  </plugins>
</build>
-- Dependency stuff --
Run Code Online (Sandbox Code Playgroud)

而使用该库的项目看起来像:

-- Artifact stuff --
<build>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
      </configuration>
    </plugin>
  </plugins>
</build>

<dependencies>
  <dependency>
    <groupId>com.maxxton</groupId>
    <artifactId>async-amqp-messaging</artifactId>
    <version>0.2</version>
  </dependency>
</dependencies>
-- Other stuff --
Run Code Online (Sandbox Code Playgroud)

我希望有人在这个问题上更先进,可以帮助找到解决这个问题的方法.如果您需要有关项目文件/结构的任何其他信息,请告诉我们.我很乐意与你分享.

更新(28-04-2015 {1})

为了测试,我创建了一个示例项目,它试图以与上述场景相同的方式加载属性文件.即使在遵循Maven文档(使用META-INF文件夹)时,我也无法加载属性.

为了这个问题,我在这里上传了测试工作区.

我希望有人可以帮我解决这个问题,因为Maven网站上描述的正常方式对我来说似乎不起作用.

更新(28-04-2015 {2})

好吧,我设法修复了问题的一部分.由于我添加了maven-assembly-plugin的配置(使用deps构建可运行的JAR),因此我能够在我的JAR文件中获得正确的结构.我添加的是:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <configuration>
                <finalName>project</finalName>
                <appendAssemblyId>false</appendAssemblyId>
                <archive>
                    <manifest>
                        <mainClass>com.test.project.Application</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
Run Code Online (Sandbox Code Playgroud)

然后当运行干净的编译程序集时:单个我设法得到正确的结构.

JAR root
    - com
    - META-INF
        - MANIFEST.MF
        - default.properties
        - custom.properties
Run Code Online (Sandbox Code Playgroud)

虽然这解决了问题的一部分.文件加载仍会导致NullPointerException.

最后更新(04-05-2015)

经过漫长的Maven斗争,我设法以我想要的方式获得所有东西.根据@Deepak和@Joop Eggen给出的建议,我做了一些关于如何将lib文件夹中的所有依赖项作为jar而不是在'uber'jar中解压缩的研究.在尝试了大量的东西后,我偶然发现了这个答案.按照说明,似乎创建了这个结构:

- runnable.jar
- lib
    - spring-amqp.jar
    - spring-core.jar
    ...
Run Code Online (Sandbox Code Playgroud)

当遵循@Joop Eggen的建议时,我设法以我想要的方式加载属性.所以似乎这个问题已得到解答.目前我还在弄清楚如何奖励每个答案,因为我无法将赏金分成两部分.我会回来的.

边注

虽然我同时给予了@Joop Eggen的赏金和答案,但并不意味着@ Deepak的答案没有贡献.它确实提供了一些关于最佳实践的重要信息,但并不像接受的答案那样完整.所以,当你在这里找到你的答案时,请给他一些功劳.

Joo*_*gen 1

获取资源有两种方式,

  • 使用绝对路径(不带/...)针对整个类路径的类加载器,
  • 对于一个类,在该类的 jar 内使用相对 ( ...) 或绝对 ( ) 路径。/...

后者似乎更直接,可以用作:

getClass().getResource("/...");
ClassInJar.class.getResource("/...");
Run Code Online (Sandbox Code Playgroud)

现在getClass()只能在非静态对象中使用,并且也很危险:实际的类可能是某个子类,而不是在库 jar 中。


关于您的应用程序的实际结构。我知道 Maven 目录约定:

src/main/java/...
src/main/resources/...
Run Code Online (Sandbox Code Playgroud)

/... 进入 jar/war 的位置;包目录。

重新组装罐子并不好。Class-Path: ...META-INF/MANIFEST.MF 中始终存在该条目。遵循基本的 Maven 约定是最好的。