Java 如何从打包在war文件中的jar文件加载资源?

Java 如何从打包在war文件中的jar文件加载资源?,java,servlets,Java,Servlets,我需要从jar加载一个属性文件。jar包含在war文件中。结构如下 ROOT.war WEB-INF lib my.jar here my.jar has following structure my.jar com test myservlet.class WEB-INF test.property 现在,我在一个servlet中编写了以下代码,如下所示: InputStream stream = getServletCon

我需要从jar加载一个属性文件。jar包含在war文件中。结构如下

ROOT.war
  WEB-INF
     lib
       my.jar

here my.jar has following structure

my.jar
  com
    test
      myservlet.class
  WEB-INF
    test.property
现在,我在一个servlet中编写了以下代码,如下所示:

InputStream stream = getServletContext().getResourceAsStream("/WEB-INF/test.properties");
Properties prop = new Properties();
prop.load(stream );
但在上面的代码中,我得到的流为null。如果我将属性文件放在ROOT.war/WEB-INF中,它可以正常工作。我很清楚,若getResourceAsStream中的路径以“/”开头,那个么它将在上下文根中搜索资源。但我如何读取位于jar中的资源,而jar又位于根应用程序的WEB-INF/lib中

谢谢和问候,
Amit Patel

您可以从给定实例访问标准类路径上的任何资源

this.getClass().getResourceAsStream("name");
例如,从您的“myservlet”类(错误的命名)

getServletContext()。getResourceAsStream()
访问web应用程序基目录上下文中的内容


将WEB-INF目录包含在jar中似乎是一种不好的风格,这样会造成混乱。您找不到更好的名称吗?

将其放在JAR的根目录中,并通过上下文类加载器而不是servletcontext获取它

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("test.properties");
// ...
/WEB-INF
文件夹约定特定于WAR文件,而不是JAR文件。摆脱它。如果您确实需要一个单独的JAR文件夹作为类路径的一部分,请使用
/META-INF

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("META-INF/test.properties");
// ...

这就是我所发现的,它对我起了作用。@BalusC提供的帮助对我起了作用。我已经整理了我的发现以及我如何验证它是否有效

我有一个maven项目,其结构如下所示

现在,当我建立这个项目;这个罐子看起来像

这里querys.properties移动到“META-INF”文件夹下。现在,如果这个jar有一个类试图使用
Thread.currentThread().getContextClassLoader().getResourceAsStream(“querys.properties”)

认为同一个文件仍然可以在资源文件夹下访问,如项目结构中所示,这是错误的。正确的方法是通过META-INF文件夹访问

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream is = classLoader.getResourceAsStream("META-INF/queries.properties");
我是如何验证的

只需创建一个简单的java项目,并将刚刚创建的jar包含到其构建路径中,然后创建一个类的实例,该实例包含上面提到的ClassLoader语句。这个新java项目中的代码应该如下所示

public static void main(String[] args){
        new Queries();
    }

其中,
查询
是您刚刚包含在构建路径中的jar中的一个类。

…或者保持原样并使用“WEB-INF/test.property”。@bMail也可以,但没有理由使用
WEB-INF
文件夹,因为servletcontext永远无法访问该文件夹。将特定于战争的文件夹约定放在普通JAR文件中也是没有意义的。同意,这并不意味着你的答案是错误的。仅仅为OP提供另一个选项以防由于某些原因改变JAR结构是困难的或不可能的。另一个有趣的点是,
getFile
有时(在WildFly的情况下)返回不正确的路径,因此您必须使用
getResourceAsStream
。我建议您阅读stackoverflow.com/a/2161583/2412477,因为它将详细介绍此问题。这是问题的首要答案,这篇文章是他的[复制品]。然而,这个问题的措辞更适合我的特殊问题,所以我就是这样来到这里的=)