在JSF中放置初始化代码的正确位置?

在JSF中放置初始化代码的正确位置?,jsf,Jsf,在JSF中,为了让它在服务器启动时只执行一次,应该在哪里放置下面的初始化片段 1. ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext(); 2. HttpSession sesion = (HttpSession)extContext.getSession(true); 3. String parA = extContext.getInitParameter("parA");

在JSF中,为了让它在服务器启动时只执行一次,应该在哪里放置下面的初始化片段

1.  ExternalContext extContext = FacesContext.getCurrentInstance().getExternalContext();
2.  HttpSession sesion = (HttpSession)extContext.getSession(true); 
3.  String parA = extContext.getInitParameter("parA");
4.  String parB = someCalculations(parA);       
5.  sesion.setAttribute("parB", parB);
基本上,我想从web.xml context param部分读取参数parA,进行一些转换,并将其包含在会话中(作为新的parB参数)

PostConstructApplicationEvent和eager=true技术不起作用,因为此时会话为空(第4行)。 ServletContextListener技术不起作用,因为FacesContext不可用


谢谢

应用程序启动时没有会话;这一要求是不可能满足的

我将您的要求解释为:

  • 执行昂贵的应用程序范围计算
  • 将此应用程序作用域结果注入其他作用域
JSF实现这一点的方法是通过托管bean。下面是一个应用程序范围bean,用于执行上下文参数的一次性转换:

package foo;

import javax.faces.bean.ApplicationScoped;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;

@ManagedBean
@ApplicationScoped
public class SomeCalculationsBean {
  @ManagedProperty("#{initParam.paraA}")
  private String paraA;

  private String someCalculation;

  public String getParaA() {
    return paraA;
  }

  public void setParaA(String paraA) {
    this.paraA = paraA;
    this.someCalculation = //do some transformation
  }

  public String getSomeCalculation() {
    return someCalculation;
  }
}
然后,可以根据需要将该值注入其他作用域:

package foo;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class SomeSessionBean {
  @ManagedProperty("#{someCalculationsBean.someCalculation}")
  private String paraB;

  public String getParaB() {
    return paraB;
  }

  public void setParaB(String paraB) {
    this.paraB = paraB;
  }
}

代码未经测试。此实现假定JSF注释支持,但您可以对
faces config.xml
bean配置执行相同的操作。

您确定要在每次启动时执行一次,而不是每次会话都执行一次吗?您正在设置会话属性。是的,我希望每次启动都执行一次。如果您忘记了会话,我可以将新参数parB放在哪里?我的意思是,类似setInitParameter(“parB”,parB)的东西,它取决于什么代码应该访问它。如果是JSFbean,那么托管bean似乎是一个合适的选择,可能是应用程序范围的。问题解决了。最后,我在应用程序范围内用eager=true声明ManagedBean。然后,在其构造函数中,我这样设置新参数:extContext.getApplicationMap().put(“parB”,parB);谢谢你的努力。问题解决了。最后,我在应用程序范围内用eager=true声明ManagedBean。然后,在其构造函数中,我这样设置新参数:extContext.getApplicationMap().put(“parB”,parB);为了单元测试的利益,您可能希望避免在托管bean中使用构造函数,转而使用依赖项注入,而不是使用
FacesContext.getCurrentInstance()
,谢谢您的建议,但我不知道怎么做(我是JSF和Spring的新手)。我实际上使用了FacesContext.getCurrentInstance()massiveli我有一篇博客文章讨论了使用
FacesContext
进行测试,还有一篇关于使用范围映射的文章。他们没有将Spring添加到混合中,并假定了解表达式语言如何解析变量并将它们放入范围。