JSF2本地化(托管bean)
我有一个用于本地化的属性文件:JSF2本地化(托管bean),jsf,jsf-2,cdi,managed-bean,Jsf,Jsf 2,Cdi,Managed Bean,我有一个用于本地化的属性文件: foo=Bar title=Widget Application 这是作为一个资源包绑定在faces配置中的: <resource-bundle> <base-name>com.example.messages.messages</base-name> <var>msgs</var> </resource-bundle> 问题是:我希望这些消息来自属性文件,这样它们也可以根
foo=Bar
title=Widget Application
这是作为一个资源包绑定在faces配置中的:
<resource-bundle>
<base-name>com.example.messages.messages</base-name>
<var>msgs</var>
</resource-bundle>
问题是:我希望这些消息来自属性文件,这样它们也可以根据区域设置进行更改。有没有一种使用注入访问属性文件的简单方法?下面是一个如何执行此操作的示例:
您想看看ResourceBundle.getBundle()
部分
您好,
拉尔斯我问了一个非常相关的问题:
在Seam论坛内:
总结如下:
我实现了一个有3个生产者的可注射资源包。
首先,您需要一个FacesContextProducer。我从Seam 3 Alpha源中取了一个
public class FacesContextProducer {
@Produces @RequestScoped
public FacesContext getFacesContext() {
FacesContext ctx = FacesContext.getCurrentInstance();
if (ctx == null)
throw new ContextNotActiveException("FacesContext is not active");
return ctx;
}
}
然后您需要一个LocaleProducer,它使用FacesContextProducer。我还从Seam 3 Alpha中获取了它
public class FacesLocaleResolver {
@Inject
FacesContext facesContext;
public boolean isActive() {
return (facesContext != null) && (facesContext.getCurrentPhaseId() != null);
}
@Produces @Faces
public Locale getLocale() {
if (facesContext.getViewRoot() != null)
return facesContext.getViewRoot().getLocale();
else
return facesContext.getApplication().getViewHandler().calculateLocale(facesContext);
}
}
现在您已经具备了创建ResourceBundleProducer的所有功能,它可以如下所示:
public class ResourceBundleProducer {
@Inject
public Locale locale;
@Inject
public FacesContext facesContext;
@Produces
public ResourceBundle getResourceBundle() {
return ResourceBundle.getBundle("/messages", facesContext.getViewRoot().getLocale() );
}
}
现在您可以@injecttheresourcebundle到您的bean中。请注意,它必须被注入到瞬态属性中,否则会出现异常,抱怨ResourceBundle不可序列化
@Named
public class MyBean {
@Inject
private transient ResourceBundle bundle;
public void testMethod() {
bundle.getString("SPECIFIC_BUNDLE_KEY");
}
}
更易于使用,例如:的消息模块 您可以单独使用JSF来实现这一点
首先在支持bean上定义托管属性。在JSF配置中,可以将托管属性的值设置为引用资源包的EL表达式
我使用Tomcat6做了如下工作。唯一需要注意的是,您不能从支持bean的构造函数访问这个值,因为JSF还没有初始化它。如果在bean生命周期的早期需要该值,则在初始化方法上使用@PostConstruct
<managed-bean>
...
<managed-property>
<property-name>messages</property-name>
<property-class>java.util.ResourceBundle</property-class>
<value>#{msgs}</value>
</managed-property>
...
</managed-bean>
<application>
...
<resource-bundle>
<base-name>com.example.messages.messages</base-name>
<var>msgs</var>
</resource-bundle>
...
</application>
...
信息
java.util.ResourceBundle
#{msgs}
...
...
com.example.messages.messages
msgs
...
这样做的好处是使您的backingbean方法更少地依赖于表示技术,因此它应该更容易测试。它还将您的代码与包的名称等细节分离
一些使用Mojarra 2.0.4-b09的测试确实显示,当用户在会话中期更改语言环境时,会出现一些小的不一致。在页面中,EL表达式使用新的区域设置,但未向支持bean提供新的ResourceBundle引用。为了保持一致,可以在EL表达式中使用bean属性值,例如使用{backingBean.messages.greeting}
代替{msgs.greeting}
。然后,page EL和支持bean将始终使用会话开始时处于活动状态的区域设置。如果用户必须在会话期间切换区域设置并获取新消息,您可以尝试创建一个请求范围的bean,并为其提供对会话bean和资源包的引用。这是一个老问题,但我添加了另一种方法。我在找别的东西,偶然发现了这个。这里的方法似乎都很复杂,但我并不觉得有那么难。玩闪粉是因为它很漂亮,如果你问我的话
给定一个文件:
/com/full/package/path/to/messages/errormessages.properties
在文件中:
SOME_ERROR_STRING=Your App Just Cratered
我创建了一个“getBundle()”方法,因为我喜欢捕捉运行时并添加一条有意义的消息,这样我就可以了解它的来源。这并不难,如果你出于某种原因突发奇想去玩属性文件,并且没有正确地更新所有的内容,这会有所帮助。我有时将其设置为私有,因为它有时是类中的一个助手方法(对我来说)。这使得try-catch杂乱无章地出现在有意义的代码之外
如果您对组织有其他想法,使用文件的完整路径可以将其放置在默认位置/目录之外的其他位置
public/private ResourceBundle getMessageResourceBundle(){
String messageBundle = "com.full.package.path.to.messages.errormessages";
ResourceBundle bundle = null;
try{
bundle = ResourceBundle.getBundle(messageBundle);
}catch(MissingResourceException ex){
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE,
"Unable to find message bundle in XYZ Class", ex);
throw ex;
}
}
public void doSomethingWithBundle(){
ResourceBundle bundle = getMessageResourceBundle();
String someString = bundle.getString("SOME_ERROR_STRING");
...
}
我在谷歌上搜索时看到了这个。但是,有没有一种更优雅的方法让容器使用@Resource(“#{msgs}”)或类似的东西来注入它?我想,因为我在使用CDI,我可以创建一个@MessageBundle
或其他东西的生产者,然后只传递回一个属性
对象……我在上一个项目中使用了这种方法-我们在DB错误方面也有同样的问题。如果这个问题仍然没有解决,我可以在下周三查看旧的来源。你是对的,这是一个有效的方法。我只是想知道是否有一种方法可以做得更优雅。我可以用CDI注射。在JSF2中,您只需使用@ManagedProperty(“#{msgs}”)私有资源包msgs代码>(使用setter)。但是检索消息时不考虑区域设置
SOME_ERROR_STRING=Your App Just Cratered
public/private ResourceBundle getMessageResourceBundle(){
String messageBundle = "com.full.package.path.to.messages.errormessages";
ResourceBundle bundle = null;
try{
bundle = ResourceBundle.getBundle(messageBundle);
}catch(MissingResourceException ex){
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE,
"Unable to find message bundle in XYZ Class", ex);
throw ex;
}
}
public void doSomethingWithBundle(){
ResourceBundle bundle = getMessageResourceBundle();
String someString = bundle.getString("SOME_ERROR_STRING");
...
}