以编程方式访问 JSF 应用程序中的属性文件 [英] Accessing properties file in a JSF application programmatically

查看:20
本文介绍了以编程方式访问 JSF 应用程序中的属性文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to access the i18n properties file I'm using in my JSF application in code. (The idea is to have a page that displays its keys and values as a table actually.)

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

The project is a maven project, and in the src/resources/localization folder, and deployed in the war file in WEB-INFclasseslocalization

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 结果都是空的.一个类似的问题是 这里,但那里也没有有用的答案.

But the variable foo turns out to be null whatever I set the path variable to, /WEB-INF/classes/localization/stat_codes.properties, "localization.stat_codes.properties" etc. A similar question is here, but there is no helpful answer there as well.

推荐答案

Class#getResourceAsStream() 可以采用相对于 Class 位置的路径你在那里使用它作为起点.因此,例如,如果该类位于 com.example 包中并且您请求路径 foo/filename.properties,那么它实际上em> 加载 com/example/foo/filename.properties 文件.但是如果你使用/foo/filename.properties,那么它会实际上从类路径根目录加载foo/filename.properties.

The Class#getResourceAsStream() can take a path which is relative to the location of the Class which you're using there as starting point. So, for example, if the class is located in the com.example package and you request the path foo/filename.properties, then it will actually load the com/example/foo/filename.properties file. But if you use /foo/filename.properties, then it will actually load foo/filename.properties from the classpath root.

所以,你的代码

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.

But in applications with a complex multiple classloader hierarchy, the one classloader isn't the other. The classloader which loaded the core Java classes does not necessarily have knowledge about files which are in the webapp's /WEB-INF/classes. So prefixing the path with / will not necessarily be the solution, it would still return null.

如果你能保证当前类对与属性文件相同的类加载器可见(因为它们在类路径的同一个子根中,例如 /WEB-INF/classes,那么你确实应该使用

If you can guarantee that the current class is visible by the same classloader as the properties files (because they're in the same sub-root of the classpath, e.g. /WEB-INF/classes, then you should indeed use

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

但是如果在某些时候,由于在运行时更容易维护/编辑,属性文件将被外部化,这样您就不需要在想要编辑文件时重建/重新部署/重新启动 web 应用程序,那么上面的代码行也可能会失败.外化位置只能由不同的类加载器访问.规范的解决方案是使用线程的上下文类加载器作为起点,它可以访问类路径中的所有资源.

But if at some point, the properties files will be externalized because of more easy maintenance/editing during runtime so that you don't need to rebuild/redeploy/restart the webapp whenever you want to edit the files, then the above line of code will likely fail as well. The externalized location would be only accessible by a different classloader. The canonical solution is to use the thread's context classloader as starting point instead, it has access to all resources in the classpath.

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

(注意这个路径不能以/开头,它总是相对于公共根)

(note that this one cannot take a path starting with /, it's always relative to the common root)

这篇关于以编程方式访问 JSF 应用程序中的属性文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆