我有一个用于本地化的属性文件:

foo=Bar
title=Widget Application

这是作为faces-config中的resource-bundle绑定(bind)的:
<resource-bundle>
    <base-name>com.example.messages.messages</base-name>
    <var>msgs</var>
</resource-bundle>

我可以使用EL在facelets View 中很好地访问它:
<title>#{msgs.title}</title>

但是,如果有类似SQLExceptions之类的东西,我需要能够从托管bean编写消息。这也可以正常工作:
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "There was an error saving this widget.", null);
FacesContext.getCurrentInstance().addMessage(null, message);

这是问题所在:我希望这些消息来自属性文件,以便它们也可以根据区域设置进行更改。有没有一种简单的方法可以使用注入(inject)来访问属性文件?

最佳答案

我问了一个非常相关的问题:
How to inject a non-serializable class (like java.util.ResourceBundle) with Weld

在Seam论坛中:
http://seamframework.org/Community/HowToCreateAnInjectableResourcebundleWithWeld

总结一下:
我实现了由3个生产者组成的可注入(inject)ResourceBundle。
首先,您需要一个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;
   }
}

然后,您需要一个使用FacesContextProducer的LocaleProducer。我也是从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() );
  }
}

现在,您可以@将ResourceBundle注入(inject)到bean中。请注意,必须将其注入(inject)到瞬时属性中,否则您将收到一个异常,提示ResourceBundle无法序列化。
@Named
public class MyBean {
  @Inject
  private transient ResourceBundle bundle;

  public void testMethod() {
    bundle.getString("SPECIFIC_BUNDLE_KEY");
  }
}

关于JSF 2本地化(托管Bean),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3478073/

10-10 09:09