我正在使用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。我真的不明白这个资源加载系统,我没有找到任何关于它的好文档。如果有人对这种机制做出了很好的解释(或者只是在文档上给出一个链接),那就太好了。 因此,主要问题是:如何加载我的资源和配置文件?
答案 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
方法,但必须在路径前添加/
。
这个问题很棘手。
首先,在这两个类中存在两个相同名称和相同签名的方法
java.lang.Class
java.lang.ClassLoader
它们具有相同的名称:getResource(String)
(和getResourceAsStream(String)
相似)。
然后,他们的参数格式不同:
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;并添加一些文件夹来构建路径。
最后,如果一个项目是一个Maven项目,默认情况下src/main/resources
在类路径中,所以我们可以使用
Class.getResource("/path-to-your-res");
或,
ClassLoader.getResource("path-to-your-res");
,在src/main/resources
下加载任何内容。
如果我们想要添加另一个资源文件夹,正如您所提到的,它是在pom.xml
中完成的。 它们也被添加到类路径中,由Maven完成。无需额外配置。
例如,如果您的config.ini
位于src/main/resources/settings
下myAvatar.gif
下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 "/"!!!
答案 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>