JSF 2.0 中 Application#getResourceBundle() 和 ResourceBundle#getBundle() 的区别
Difference between by Application#getResourceBundle() and ResourceBundle#getBundle() in JSF 2.0
为了从资源包中检索字符串,我试图比较这两种方法的结果,下面是代码示例:
第一个例子:
baseName:资源包的完全限定名称(<resource-bundle>
中的<base-name>
)。
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
ResourceBundle bundle = app.getResourceBundle(context, baseName);
第二个例子:
varName:是表示<resource-bundle>
中的<var></var>
的字符串
FacesContext context = FacesContext.getCurrentInstance();
Locale locale = context .getViewRoot().getLocale();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
ResourceBundle bundle = ResourceBundle.getBundle(varName, locale, loader);
这两个例子有什么区别?如果没有区别,获取 ResourceBundle 的最佳做法是什么(使用 Application#getMessageBundle() 或 ResourceBundle#getBundle())?
首先,您混淆了 varName/baseName 的方法。实际的做法是:
Application#getResourceBundle()
varName
: is the String representing the <resource-bundle><var>
in faces-config.xml
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
ResourceBundle bundle = application.getResourceBundle(context, varName);
ResourceBundle#getBundle()
baseName
: is the fully qualified name of the resource bundle, like <resource-bundle><base-name>
FacesContext context = FacesContext.getCurrentInstance();
Locale locale = context.getViewRoot().getLocale();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, loader);
前者通过 JSF Application
获取它,后者在幕后也使用 UIViewRoot#getLocale()
(回退到 Locale#getDefault()
),而后者直接获取它。
至于技术和最终结果,没有区别。在这两种情况下,您将获得完全相同的捆绑包(前提是语言环境是正确的)。但是,至于可维护性,它肯定是不同的。资源包属于“配置”,必须外部化(在 faces-config.xml
中)。
像 baseName
那样对 FQN 进行硬编码是一种糟糕的做法。如果不重新编译和重新构建所有代码,您无法轻松快速地更改 FQN。如果是在 3rd party JAR 文件中,那就更麻烦了。否则,您可以在您的 web 应用程序内部用同一个 <var>
上的另一个 <resource-bundle>
覆盖它。此外,JSF component/utility 库可能会提供一个自己的 Application
包装器,它可能会装饰 getResourceBundle()
调用以做一些很棒的事情。如果您直接通过 ResourceBundle#getBundle()
.
获得它,那将是不可能的
顺便说一句,还有第三种方法:注入即可。
在 JSF 托管 bean 中,提供了一个 <var>text</var>
:
@ManagedProperty("#{text}")
private ResourceBundle text;
或者在 CDI 托管 bean 中:
@Inject
private PropertyResourceBundle text;
与此制作人:
public class BundleProducer {
@Produces
public PropertyResourceBundle getBundle() {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().evaluateExpressionGet(context, "#{text}", PropertyResourceBundle.class);
}
}
注意:#{text}
捆绑包的 EL 评估在幕后使用 Application#getResourceBundle()
。
为了从资源包中检索字符串,我试图比较这两种方法的结果,下面是代码示例:
第一个例子:
baseName:资源包的完全限定名称(<resource-bundle>
中的<base-name>
)。
FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
ResourceBundle bundle = app.getResourceBundle(context, baseName);
第二个例子:
varName:是表示<resource-bundle>
<var></var>
的字符串
FacesContext context = FacesContext.getCurrentInstance();
Locale locale = context .getViewRoot().getLocale();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
ResourceBundle bundle = ResourceBundle.getBundle(varName, locale, loader);
这两个例子有什么区别?如果没有区别,获取 ResourceBundle 的最佳做法是什么(使用 Application#getMessageBundle() 或 ResourceBundle#getBundle())?
首先,您混淆了 varName/baseName 的方法。实际的做法是:
Application#getResourceBundle()
varName
: is the String representing the<resource-bundle><var>
infaces-config.xml
FacesContext context = FacesContext.getCurrentInstance(); Application application = context.getApplication(); ResourceBundle bundle = application.getResourceBundle(context, varName);
ResourceBundle#getBundle()
baseName
: is the fully qualified name of the resource bundle, like<resource-bundle><base-name>
FacesContext context = FacesContext.getCurrentInstance(); Locale locale = context.getViewRoot().getLocale(); ClassLoader loader = Thread.currentThread().getContextClassLoader(); ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale, loader);
前者通过 JSF Application
获取它,后者在幕后也使用 UIViewRoot#getLocale()
(回退到 Locale#getDefault()
),而后者直接获取它。
至于技术和最终结果,没有区别。在这两种情况下,您将获得完全相同的捆绑包(前提是语言环境是正确的)。但是,至于可维护性,它肯定是不同的。资源包属于“配置”,必须外部化(在 faces-config.xml
中)。
像 baseName
那样对 FQN 进行硬编码是一种糟糕的做法。如果不重新编译和重新构建所有代码,您无法轻松快速地更改 FQN。如果是在 3rd party JAR 文件中,那就更麻烦了。否则,您可以在您的 web 应用程序内部用同一个 <var>
上的另一个 <resource-bundle>
覆盖它。此外,JSF component/utility 库可能会提供一个自己的 Application
包装器,它可能会装饰 getResourceBundle()
调用以做一些很棒的事情。如果您直接通过 ResourceBundle#getBundle()
.
顺便说一句,还有第三种方法:注入即可。
在 JSF 托管 bean 中,提供了一个 <var>text</var>
:
@ManagedProperty("#{text}")
private ResourceBundle text;
或者在 CDI 托管 bean 中:
@Inject
private PropertyResourceBundle text;
与此制作人:
public class BundleProducer {
@Produces
public PropertyResourceBundle getBundle() {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().evaluateExpressionGet(context, "#{text}", PropertyResourceBundle.class);
}
}
注意:#{text}
捆绑包的 EL 评估在幕后使用 Application#getResourceBundle()
。