JSF 2.0中的Application#getResourceBundle()和ResourceBundle#getBundle()之间的区别

时间:2015-01-13 17:14:08

标签: jsf jsf-2 resourcebundle facescontext

为了从资源包中检索字符串,我试图比较这两种方法的结果,下面是代码示例:

第一个例子:

baseName:资源包的完全限定名称(<base-name>中的<resource-bundle>)。

FacesContext context = FacesContext.getCurrentInstance();
Application app = context.getApplication();
ResourceBundle bundle = app.getResourceBundle(context, baseName);

第二个例子:

varName:是表示<var></var>

<resource-bundle>的字符串
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())的最佳做法是什么?

1 个答案:

答案 0 :(得分:8)

首先,您混合了方法的varName / baseName。实际的方法是:

  

Application#getResourceBundle()

     

varName:是表示<resource-bundle><var>

faces-config.xml的字符串
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
ResourceBundle bundle = application.getResourceBundle(context, varName);
  

ResourceBundle#getBundle()

     

baseName:是资源包的完全限定名称,如<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。如果它是在第三方JAR文件中,那将更加麻烦。否则,您可以在网络应用中使用同一<resource-bundle>上的其他<var>覆盖它。此外,JSF组件/实用程序库可能提供一个自己的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);
    }

}

注意:EL {#{text}捆绑使用评估涵盖Application#getResourceBundle()