以编程方式访问JSF应用程序中的属性文件

11

我正在尝试在代码中访问我在JSF应用程序中使用的i18n属性文件。(实际上,想要创建一个以表格形式显示其键和值的页面。)

该项目是一个maven项目,在src/resources/localization文件夹中,并部署在WEB-INF\classes\localization\中的war文件中。

java.util.Properties prop = new java.util.Properties();
String path = "localization/stat_codes.properties";
InputStream foo = prop.getClass().getResourceAsStream(path);

但是无论我将路径变量设置为/WEB-INF/classes/localization/stat_codes.properties,"localization.stat_codes.properties"等等,变量foo最终都会变成null。这里有一个类似的问题(链接),但那里也没有什么有用的答案。

2个回答

23
Class#getResourceAsStream()方法可以接收相对于所在的Class位置的路径作为起点。例如,如果该类位于com.example包中,并请求路径foo/filename.properties,则实际上它会加载com/example/foo/filename.properties文件。但是,如果使用/foo/filename.properties,则实际上它会从类路径根目录加载foo/filename.properties文件。
因此,您的代码:
java.util.Properties prop = new java.util.Properties();
String path = "localization/stat_codes.properties";
InputStream foo = prop.getClass().getResourceAsStream(path);

实际上会查找 java/util/localization/stat_codes.properties 文件。

但是在具有复杂多重类加载器层次结构的应用程序中,一个类加载器不是另一个类加载器。 加载核心Java类的类加载器不一定知道位于web应用程序的/ WEB-INF / classes 中的文件。 因此,在路径前加上/并不一定是解决方案,它仍然会返回null

如果您可以保证当前类可由与属性文件可见的同一类加载器看到(因为它们位于类路径的同一子根目录中,例如/ WEB-INF / classes ),那么您确实应该使用它。

<code>String path = "/localization/stat_codes.properties";
InputStream foo = this.getClass().getResourceAsStream(path);
</code>

但是,如果在某个时候,由于在运行时更轻松地进行维护/编辑,因此属性文件将被外部化,以便您不需要在想要编辑文件时重新构建/部署/重新启动Web应用程序,那么上面的代码行也很可能失败。外部位置仅可由不同的类加载器访问。规范的解决方案是使用线程的上下文类加载器作为起点,它可以访问类路径中的所有资源。

<code>String path = "localization/stat_codes.properties";
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream foo = loader.getResourceAsStream(path);
</code>

(请注意,此方法无法接受以/开头的路径,它始终相对于共同的根目录)

另请参阅:


1
似乎罪魁祸首是prop对象,我原以为任何对象都可以,但它必须是当前对象(this),在该对象上调用getClass()方法。此外,路径应该以/开头,因为localization目录位于WEB-INF/classes中。
String path = "localization/stat_codes.properties";
InputStream foo = this.getClass().getResourceAsStream(path);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接