在JAR中加载属性文件?

And*_*ndy 58 java resources maven-2 properties classloader

当我的网络应用程序所依赖的其中一个罐试图从jar中加载属性文件时,我遇到了麻烦.这是jar中的代码.

static
{
    Properties props = new Properties();
    try 
    {
        props.load(ClassLoader.getSystemResourceAsStream("someProps.properties"));
    } catch (IOException e) 
    {
        e.printStackTrace();
    }
    someProperty = props.getProperty("someKey");
}
Run Code Online (Sandbox Code Playgroud)

属性文件位于Maven项目的"src/main/resources"目录中.当我在Eclipse中的junit测试中运行此代码时,它执行得很好.当项目使用Maven构建到jar中,并作为依赖项包含在我的Web应用程序中时,它无法找到属性文件.我知道属性文件位于依赖于jar的基本目录中,我不知道如何解决这个问题.

mdm*_*dma 74

问题是你正在使用getSystemResourceAsStream.使用简单getResourceAsStream.系统资源从系统类加载器加载,几乎可以肯定不是在作为webapp运行时加载jar的类加载器.

它在Eclipse中工作,因为在启动应用程序时,系统类加载器配置了jar作为其类路径的一部分.(例如,java -jar my.jar将在系统类加载器中加载my.jar.)Web应用程序不是这种情况 - 应用程序服务器使用复杂的类加载将Web应用程序彼此隔离,并与应用程序服务器的内部隔离.例如,请参阅tomcat类加载器的方法,以及使用的类加载器层次结构的图表.

编辑:通常,您将调用getClass().getResourceAsStream()在类路径中检索资源,但是当您在静态初始化程序中获取资源时,您需要显式命名要加载的类加载器中的类.最简单的方法是使用包含静态初始化程序的类,例如

[public] class MyClass {
  static
  {
    ...
    props.load(MyClass.class.getResourceAsStream("/someProps.properties"));
  }
}
Run Code Online (Sandbox Code Playgroud)

  • @binil - 我对此进行了一些研究,并了解当您想要脱离类加载器的层次结构并使用不是您的类加载器祖先之一的类加载器时,会使用上下文类加载器。这里不需要上下文类加载器,因为资源位于同一个 web 应用程序中,因此与 MyClass 位于同一个类加载器中。 (2认同)

Pas*_*ent 14

有关记录,请参阅如何向JAR添加资源?(图示为单元测试,但同样适用于"常规"资源):

要将资源添加到单元测试的类路径中,您将遵循与向JAR添加资源相同的模式,但将资源放入的目录除外 ${basedir}/src/test/resources.此时,您将拥有一个项目目录结构,如下所示:

my-app
|-- pom.xml
`-- src
    |-- main
    |   |-- java
    |   |   `-- com
    |   |       `-- mycompany
    |   |           `-- app
    |   |               `-- App.java
    |   `-- resources
    |       `-- META-INF
    |           |-- application.properties
    `-- test
        |-- java
        |   `-- com
        |       `-- mycompany
        |           `-- app
        |               `-- AppTest.java
        `-- resources
            `-- test.properties
Run Code Online (Sandbox Code Playgroud)

在单元测试中,您可以使用以下代码的简单代码段来访问测试所需的资源:

...

// Retrieve resource
InputStream is = getClass().getResourceAsStream("/test.properties" );

// Do something with the resource

...
Run Code Online (Sandbox Code Playgroud)