2010-05-12 98 views
50

我遇到麻烦时,我的Web应用程序所依赖的一个罐子试图从jar中加载属性文件。这是jar中的代码。在JAR中加载属性文件?

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

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

请帮忙!

回答

65

问题是,您正在使用getSystemResourceAsStream。只需使用getResourceAsStream即可。从系统类加载器加载系统资源,这几乎不是当您的jar作为webapp运行时加载到的类加载器。

它在Eclipse中起作用,因为启动应用程序时,系统类加载器会使用您的jar作为其类路径的一部分进行配置。 (例如,java -jar my.jar会将my.jar加载到系统类加载器中。)Web应用程序并不是这种情况 - 应用程序服务器使用复杂的类加载将应用程序彼此和应用程序服务器的内部隔离。例如,请参见tomcat classloader how-to以及使用的类加载器层次结构图。编辑:通常,您将调用getClass()。getResourceAsStream()来检索类路径中的资源,但是当您在静态初始化程序中获取资源时,您需要显式地命名该类中的类类加载器,你想从中加载。最简单的方法是使用包含静态初始化程序的类,例如

[public] class MyClass { 
    static 
    { 
    ... 
    props.load(MyClass.class.getResourceAsStream("/someProps.properties")); 
    } 
} 
+1

此外,使用线程的上下文类加载器在'Thread.currentThread()getContextClassloader()' – 2010-05-12 01:15:16

+0

@binilŤ小费的小费。我从来不需要这样做 - 何时需要? – mdma 2010-05-12 01:25:10

+1

@binil - 我已经研究了这一点,并且理解上下文classloader用于当您想离开classloader的层次结构并使用不是您的类加载器的祖先之一的类加载器时。上下文类加载器在这里不是必需的,因为资源在同一个webapp中,因此和MyClass在同一个类加载器中。 – mdma 2010-05-12 11:52:09

13

根据记录,这是记录在How do I add resources to my JAR?(单元测试说明,但同样适用于“常规”资源):

将资源添加到类路径 单元测试,除了将 放置资源的目录为 ${basedir}/src/test/resources之外,您遵循与您将资源 添加到JAR的操作相同的 模式。在 这一点上,你将有一个看起来 类似以下的项目 目录结构:

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 

在单元测试中,你可以使用一个简单的 代码片段像下面这样 访问所需资源 测试:

... 

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

// Do something with the resource 

... 
+0

是一个标准结构,在'test'和'main'中有资源吗?这只是一个maven约定,或者是JAR文档本身的一部分? – Thufir 2017-08-18 13:13:41