如何从托管 bean 中获取消息包字符串?

Posted

技术标签:

【中文标题】如何从托管 bean 中获取消息包字符串?【英文标题】:How can I get a message bundle string from inside a managed 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 的链接,它解释了“消息”包和“资源”包之间的区别。

【问题讨论】:

【参考方案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,但我更正了,感谢您的通知

以上是关于如何从托管 bean 中获取消息包字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何在托管代码(C#)中从本机代码(C++)获取字符串数组

从 JSF 中的托管 bean 获取资源文件的路径

如何从过滤器中获取 SessionScoped CDI bean?

从托管 bean 中的 ADF SelectOneChoice 获取选定项目

JSF 获取托管 bean 中的当前操作

在另一个托管 bean 中获取托管 bean 引用