Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JSF2本地化(托管bean)_Jsf_Jsf 2_Cdi_Managed Bean - Fatal编程技术网

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");
    ...
}