如何从java代码访问消息包以根据当前区域设置获取消息?
我尝试使用@ManagedProperty
,如下所示:
@Named
@SessionScoped
public class UserBean implements Serializable {
@ManagedProperty("#{msg}")
private ResourceBundle bundle;
// ...
public void setBundle(ResourceBundle bundle) {
this.bundle = bundle;
}
}
但是,它仍为null
。它似乎在@Named
内无效。
这是我在faces-context.xml
中注册资源包的方式:
<application>
<message-bundle>validator.messages</message-bundle>
<locale-config>
<supported-locale>en_US</supported-locale>
<supported-locale>ua_UA</supported-locale>
</locale-config>
<resource-bundle>
<base-name>lang.messages</base-name>
<var>msg</var>
</resource-bundle>
</application>
作者发表:
@BalusC我收到错误
16:29:10,968 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/WEBSearchPrime_JB_lang].[Faces Servlet]] (http-localhost-127.0.0.1-8080-1) Servlet.service() for servlet Faces Servlet threw exception: org.jboss.weld.exceptions.IllegalProductException: WELD-000054 Producers cannot produce non-serializable instances for injection into non-transient fields of passivating beans\\n\\nProducer\: Producer Method [PropertyResourceBundle] with qualifiers [@Any @Default] declared as [[method] @Produces public util.BundleProducer.getBundle()]\\nInjection Point\: [field] @Inject private model.UserBean.bundle
请注意,我还放了Serializable接口
答案 0 :(得分:9)
您无法在@ManagedProperty
注释的CDI托管bean中使用@Named
。您只能在使用@ManagedBean
注释的JSF托管bean中使用它。
CDI没有任何注释来注入EL表达式的评估结果,如@ManagedProperty
。 CDI方法使用带有@Produces
的“CDI生成器”,其中返回具体类型,如果基于PropertyResourceBundle
文件的资源包,则返回.properties
。
只需将此类放在WAR中的某个位置:
@RequestScoped
public class BundleProducer {
@Produces
public PropertyResourceBundle getBundle() {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().evaluateExpressionGet(context, "#{msg}", PropertyResourceBundle.class);
}
}
现在您可以按如下方式注入它:
@Inject
private PropertyResourceBundle bundle;
答案 1 :(得分:1)
除了BalusC的答案:
自JSF 2.3起,还可以注入在faces-config.xml中定义的资源束,而无需使用生产方方法。有一个与javax.faces.annotation.ManagedProperty
一起使用的新注释...annotation
(注意,它在...bean
包中,而不是@Inject
包中):
// ...
import javax.faces.annotation.ManagedProperty;
// ...
@Named
@SessionScoped
public class UserBean implements Serializable {
// ...
@Inject
@ManagedProperty("#{msg}")
private ResourceBundle bundle;
// ...
}
答案 2 :(得分:0)
也许我弄错了,但是实际上所提供的解决方案都不适合我的用例。因此,我提供了另一个对我有用的答案。
有了BalusC提供的答案,我遇到了以下问题:
当我使用基于ajax的验证时,我的bean是@ViewScoped
,并且
必须可序列化。既不是ResourceBundle
也不是
PropertyResourceBundle
是可序列化的,因此无法注入
@Dependent
范围。
如果我尝试将生产者更改为使用@RequestScoped
,它也会失败
因为ResourceBundle
不可用于定义final
的代理
方法。
当我使用JSF 2.3(JBoss 7.2EAP)时,我采用了JörenHaag提供的解决方案,并且最初似乎可行。像原始问题一样,我也有多个受支持的语言环境,用户可以在语言环境之间进行切换(在我的情况下为ca
和es
)
我遇到Jören答案的问题是
创建bean时将评估返回的ResourceBundle
。在他的示例中,他正在使用@SessionScoped
bean。创建会话时,将使用当前语言环境解析ResourceBundle
。如果用户以后更改语言环境,则ResourceBundle
将不会更新。如果用户可以更改语言而不更改视图,则@ViewScoped
bean也会发生这种情况。
我还遇到了另一个需要使用<f:viewAction>
预加载数据的bean问题。在这种情况下,bean是较早实例化的,因此在用ResourceBundle
设置用户区域设置之前,注入了<f:view locale="#{sessionBean.locale}">
。因此,如果用户浏览器使用的是es
,但是用户将语言环境更改为ca
,则捆绑包将加载es
,因为视图语言环境未设置为{{1 }}和ca
,直到呈现阶段。
要克服这个问题,对于使用注入的问题的用例,对我而言有效的解决方案是:
sessionBean.locale
由于原始问题不需要注入,因此仅询问如何使用当前语言环境访问资源束,无注入的解决方案以及每次{{1}都不会评估EL表达式@SessionScoped
public class UserBean implements Serializable {
@Inject
@ManagedProperty("#{msg}")
private Instance<ResourceBundle> bundle;
// ....
public void someAction() {
String message = bundle.get().getString("someLabel");
// ...
}
}
的开销}称为:
#{msg}