【问题标题】:How can I get a message bundle string from inside a managed bean?如何从托管 bean 中获取消息包字符串?
【发布时间】:2011-09-10 12:07:07
【问题描述】:

我希望能够从 JSF 2 托管 bean 内部的消息包中检索字符串。这将在字符串用作FacesMessage 中的摘要或详细信息参数或用作抛出异常中的消息的情况下完成。

我想确保托管 bean 为用户的语言环境加载正确的消息包。我不清楚如何使用 JSF API 调用从托管 bean 执行此操作。

我的配置是:

  • 使用 Tomcat 7 作为容器,因此解决方案不能依赖仅在完整应用服务器容器中工作的 API 调用
  • 使用 JSF 2 参考实现 (Mojarra)
  • 不使用任何允许 CDI 的库

注意:我确实看到了this similar question,但这取决于我的配置中不可用的功能

编辑:我在最初的问题中犯了一个错误。我想问的是“如何从托管 bean 中获取 resource 捆绑字符串”? BalusC 给出了我所问的正确答案。我真正想问的解决方案非常相似:

public static String getResourceBundleString(
            String resourceBundleName,
            String resourceBundleKey)
        throws MissingResourceException {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ResourceBundle bundle = 
        facesContext.getApplication().getResourceBundle(
            facesContext, resourceBundleName);
    return bundle.getString(resourceBundleKey);
}

另外,这里有一个指向another question 的链接,它解释了“消息”包和“资源”包之间的区别。

【问题讨论】:

    标签: jsf jsf-2 managed-bean message-bundle


    【解决方案1】:

    您可以通过Application#getMessageBundle() 获取<message-bundle> 的完整限定包名称。您可以通过UIViewRoot#getLocale() 获取当前语言环境。您可以从完全合格的捆绑包中获得ResourceBundle ResourceBundle#getBundle() 的名称和语言环境。

    所以,总结一下:

    FacesContext facesContext = FacesContext.getCurrentInstance();
    String messageBundleName = facesContext.getApplication().getMessageBundle();
    Locale locale = facesContext.getViewRoot().getLocale();
    ResourceBundle bundle = ResourceBundle.getBundle(messageBundleName, locale);
    // ...
    

    更新:根据问题中的错误,您实际上想要获取由<resource-bundle><base-name> 标识的捆绑包。不幸的是,标准的 JSF API 不能直接使用它。您可以在代码中硬编码相同的基本名称并将上面示例中的 messageBundleName 替换为它,或者将其作为托管属性注入到请求范围 bean 中的 <var> 上:

    @ManagedProperty("#{msg}")
    private ResourceBundle bundle; // +setter
    

    【讨论】:

    • 我刚试过这个,但 messageBundleName 被设置为 null,这会导致在对 getBundle() 的调用中出现 NullPointerException
    • 我的错误。我对资源包和消息包感到困惑。请参阅我对原始问题的编辑。
    • 后一种解决方案不起作用。它为 bundle 报告 NullPointerException。
    • @Emerald:完全遵循问题和答案中提供的信息时,对我和其他任何人都有效。如果您仍然无法弄清楚,只需按 [] 按钮,而不是用误导性和无信息的“不起作用”cmets 污染有效答案。
    • @BalusC 这仅适用于英语和德语的消息包,但不适用于保加利亚语。你知道为什么吗?
    【解决方案2】:
    FacesContext context = FacesContext.getCurrentInstance();
    ResourceBundle bundle = context.getApplication().getResourceBundle(context, "msg");
    String message = bundle.getString("key");
    

    这里的关键是您要从属性文件中访问的属性名称。

           message = This is "message"
    

    此条目来自 messages.properites 文件。而“消息”是“关键”。

    【讨论】:

    • 确实这就像一个魅力。我确实想知道为什么您需要将上下文指定为参数。
    • "msg" 是 faces config 中定义的变量
    【解决方案3】:

    有两种方法可以在托管 bean 中获取 String 资源包,使用 baseNamevarName(请参阅下面的每个定义):

    使用 varName:

    varName: 是代表<resource-bundle><var></var>的字符串

    FacesContext context = FacesContext.getCurrentInstance();
    Application app = context.getApplication();
    ResourceBundle bundle = app.getResourceBundle(context, varName);
    String msg = bundle.getString("key");
    

    使用 baseName:

    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);
    String msg = bundle.getString("key");
    

    【讨论】:

    • 不正确。 ResourceBundle#getBundle() 将基本名称作为第一个参数。也许你很困惑,因为你给了它们两个相同的值。
    • @BalusC 我在代码中混淆了 varName 和 baseName,但我更正了,感谢您的通知
    猜你喜欢
    • 1970-01-01
    • 2015-06-05
    • 2014-09-29
    • 1970-01-01
    • 2012-12-12
    • 2011-07-25
    • 2019-05-11
    • 2016-09-17
    • 1970-01-01
    相关资源
    最近更新 更多