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

LMn*_*net 7 java resources config classloader maven

我正在使用Maven进行桌面应用.我读到了Maven标准目录布局,我现在有这个项目结构:

App
|-- pom.xml
`-- src
    |-- main
        |-- java
        |   `-- java classes
        |-- resources
        |   `-- images
        |       `-- app images
        `--config
           `--config.xml
Run Code Online (Sandbox Code Playgroud)

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

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

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

Wes*_*Gun 9

你可以像你所做getResourceAsStream()java.lang.Class那样使用方法,但你必须/在路径之前添加。


这个问题很棘手。

1. 两个同名方法

首先,在这两个类中存在两个同名同名的方法:

java.lang.Class
java.lang.ClassLoader
Run Code Online (Sandbox Code Playgroud)

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

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

然后,它们的参数具有不同的格式:

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

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

如何将文件夹添加到类路径?在 Eclipse 中,我们解析到项目的上下文菜单:“构建路径”-“配置构建路径...”并添加一些文件夹到构建路径。

3. 说到 Maven

最后,如果一个项目是Maven项目,默认src/main/resources是在classpath中,所以我们可以使用

Class.getResource("/path-to-your-res");
Run Code Online (Sandbox Code Playgroud)

或者,

ClassLoader.getResource("path-to-your-res");
Run Code Online (Sandbox Code Playgroud)

, 加载下的任何东西src/main/resources

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

4. 例子

例如,如果您config.inisrc/main/resources/settings, myAvatar.gifunder src/main/images,您可以执行以下操作:

pom.xml

<build>
    <resources>
        <resource>
            <directory>src/main/images</directory>
        </resource>
    </resources>
</build>
Run Code Online (Sandbox Code Playgroud)

在代码中:

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.
Run Code Online (Sandbox Code Playgroud)

我们必须使用/上面的。

或者,使用类加载器:

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


LMn*_*net 7

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

<build>
    <resources>
        <resource>
            <directory>src/main/config</directory>
        </resource>
    </resources>
</build>
Run Code Online (Sandbox Code Playgroud)

而且工作的java代码是:

InputStream image = this.getClass().getClassLoader().getResourceAsStream("images/image.png");
InputStream config = ClassLoader.getSystemResourceAsStream("config.xml");
Run Code Online (Sandbox Code Playgroud)

  • 只需一个小小的注释,通过向您的资源添加配置,maven会将其视为资源.因此它也将包含在已编译的jar中,这可能是您不想对配置文件执行的操作. (2认同)