9

我正在使用 Maven 进行桌面应用。我阅读了有关Maven 标准目录布局的信息,现在我有这个项目结构:

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");
    }        
}

但是图像和配置变量包含空值。我正在尝试不同的加载变体(从根文件夹,使用 this.getClass() 而不是 Preferences.class 等),但我总是有 null。我真的不了解这个资源加载系统,也没有找到任何好的文档。如果有人对这种机制给出一个很好的解释(或者只是在文档上提供一个链接),那就太好了。所以,主要问题是:如何加载我的资源和配置文件?

4

6 回答 6

10

您可以像以前一样使用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("...") 和 NullPointerException

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

3. 谈到 Maven

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

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

或者,

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

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

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

4. 例子

例如,如果你config.ini是 under src/main/resources/settingsmyAvatar.gifunder src/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 "/"!!!
于 2017-09-27T07:40:48.117 回答
7

我想我找到了解决方案。正如 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");
于 2013-05-04T12:53:45.267 回答
3
public Preferences() {
    InputStream image = this.getClass().getClassLoader().getResourceAsStream("image.png");
    InputStream config = this.getClass().getClassLoader().getResourceAsStream("config.xml")
} 
于 2013-05-04T12:28:03.760 回答
2

如何使用这种方法:

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 目录中。同样,这取决于它是如何构建的。

于 2013-05-04T12:28:01.020 回答
1

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

于 2017-02-09T19:36:47.940 回答
0

这是一个已回答的老问题,但我发现您需要使用包含标签集,否则在您调用时它不会找到资源。

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>
于 2020-10-07T22:06:49.460 回答