maven项目中的资源和配置加载

时间:2013-05-04 12:21:10

标签: java maven resources classloader config

我正在使用Maven进行桌面应用。我读到了Maven standart directory layout,我现在有了这个项目结构:

App
|-- pom.xml
`-- src
    |-- main
        |-- java
        |   `-- java classes
        |-- resources
        |   `-- images
        |       `-- app images
        `--config
           `--config.xml

我想找到一种加载资源和配置文件的方法。我阅读了一些文章和主题并找到了这个(我的代码中的简化示例):

//class for loading config
public class Preferences {
    public Preferences() {
        InputStream image = Preferences.class.getResourceAsStream("images/image.png");
        InputStream config = Preferences.class.getResourceAsStream("config.xml");
    }        
}

但是image和config变量包含null。我正在尝试不同的加载变体(从根文件夹,使用this.getClass()而不是Preferences.class,以及其他),但我总是为null。我真的不明白这个资源加载系统,我没有找到任何关于它的好文档。如果有人对这种机制做出了很好的解释(或者只是在文档上给出一个链接),那就太好了。 因此,主要问题是:如何加载我的资源和配置文件?

6 个答案:

答案 0 :(得分:6)

我想我找到了解决方案。正如Juned Ahsan和mR_fr0g所写,我需要使用ClassLoader类,而不是this.getClass()。getResource()。但是,它仅适用于资源文件夹。但是maven允许添加其他文件夹作为资源文件夹。我只需要将此部分添加到pom.xml:

<build>
    <resources>
        <resource>
            <directory>src/main/config</directory>
        </resource>
    </resources>
</build>

使用java代码是:

InputStream image = this.getClass().getClassLoader().getResourceAsStream("images/image.png");
InputStream config = ClassLoader.getSystemResourceAsStream("config.xml");

答案 1 :(得分:4)

您可以使用getResourceAsStream() java.lang.Class方法,但必须在路径前添加/

这个问题很棘手。

1。两个同名的方法

首先,在这两个类中存在两个相同名称和相同签名的方法

java.lang.Class
java.lang.ClassLoader

它们具有相同的名称:getResource(String)(和getResourceAsStream(String)相似)。

2。他们接受不同格式的参数

然后,他们的参数格式不同:

  • 方法java.lang.Class.getResouce<asStream>()接受包含和不包含前导/的路径,从而产生不同的资源搜索策略。如果路径没有/,Java将搜索.class文件所在的包/文件夹中的资源。如果它有/,Java将从类路径根开始搜索。
  • 方法java.lang.ClassLoader.getResource<asStream>()仅接受没有/的路径,因为它始终从类路径中搜索。在基于类路径的路径中,/不是有效字符。 *

    *:正如这个回答所述:this.getClass().getClassLoader().getResource("...") and NullPointerException

如何将文件夹添加到classpath?在Eclipse中,我们解析为项目的上下文菜单:&#34;构建路径&#34; - &#34;配置构建路径...&#34;并添加一些文件夹来构建路径。

3。说到Maven

最后,如果一个项目是一个Maven项目,默认情况下src/main/resources在类路径中,所以我们可以使用

Class.getResource("/path-to-your-res");

或,

ClassLoader.getResource("path-to-your-res");

,在src/main/resources下加载任何内容。

如果我们想要添加另一个资源文件夹,正如您所提到的,它是在pom.xml中完成的。 它们也被添加到类路径中,由Maven完成。无需额外配置。

4。实施例

例如,如果您的config.ini位于src/main/resources/settingsmyAvatar.gifsrc/main/images,则可以执行以下操作:

pom.xml

<build>
    <resources>
        <resource>
            <directory>src/main/images</directory>
        </resource>
    </resources>
</build>

在代码中:

URL urlConfig = MyClass.class.getResource("/settings/config.ini"); //by default "src/main/resources/" is in classpath and no config needs to be changed.
InputStream inputAvatar = MyClass.class.getResourceAsStream("/myAvatar.gif"); //with changes in pom.xml now "src/main/images" is counted as resource folder, and added to classpath. So we use it directly.

我们必须使用上面的/

或者,使用ClassLoader:

URL urlConfig = MyClass.class.getClassLoader().getResource("settings/config.ini"); //no leading "/"!!!
InputStream inputAvatar = MyClass.class.getClassLoader().getResourceAsStream("myAvatar.gif"); //no leading "/"!!!

答案 2 :(得分:3)

public Preferences() {
    InputStream image = this.getClass().getClassLoader().getResourceAsStream("image.png");
    InputStream config = this.getClass().getClassLoader().getResourceAsStream("config.xml")
} 

答案 3 :(得分:2)

如何使用此appraoch:

InputStream file = ClassLoader.getSystemResourceAsStream("res.txt");

InputStream file = Thread.currentThread().getContextClassLoader().getResourceAsStream("MyProperty.properties");

正如您目前所拥有的那样,它将在类路径的顶部查找MyProperty.properties文件。可以在你的src / main / resources目录或其他src文件夹中 - 它取决于你的应用程序(jar / war)的构建方式。

如果你正在构建一个jar,那么你应该能够解压缩它并在jar的顶层看到你的属性文件。如果你正在构建一个战争,也许它应该在WEB-INF / classes目录中。同样,这取决于它是如何构建的。

答案 4 :(得分:1)

尝试之前构建项目。 如果您只是将文件放在资源文件夹中,那么您需要构建项目以将新资源文件复制到目标文件夹

答案 5 :(得分:0)

这是一个古老的已回答问题,但是我发现您需要使用 include 标记集,否则在调用时将找不到资源。

ClassLoader.getSystemResource("config.xml").

我在JDK14上使用最新的Maven(2020年10月)

这是有效的xml。希望它能按我在此处的解决方案中所述的那样对您有所帮助,并且直到我的xml如下所示时,它才起作用。

<build>                
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.xml</include> 
<!-- or whatever other file extensions you want to include -->
            </includes>
        </resource>
    </resources>        
</build>