我正在构建一个JSF + Facelets Web应用程序,其中一个是每隔一段时间扫描一个目录并为任何更改编制索引的方法。此方法是应用程序范围内的bean的一部分。我已经构建了一个TimerTask的子类来每隔X毫秒调用一次该方法。我的问题是将bean初始化。我可以在页面上引用bean,当我转到页面时,bean被初始化,并按照指示工作;我想要的是在初始化Web上下文时初始化bean,这样它就不需要页面访问来启动索引方法。谷歌已经展示了一些人想要这个功能,但除了与Spring集成之外没有真正的解决方案,我真的不想仅仅为了获得这个功能。
我已经尝试过使用具有“load-on-startup”设置的servlet和一个ServletContextListener以使事情继续进行,并且无法正确设置,因为没有'可以使用FacesContext,或者因为我无法从JSF环境引用bean。
有没有办法在Web应用程序启动时初始化JSF bean?
答案 0 :(得分:14)
如果您的代码调用FacesContext,它将无法在与JSF请求生命周期关联的线程之外工作。为每个请求创建一个FacesContext对象,并将其置于请求的末尾。您可以通过static call获取它的原因是因为它在请求开始时设置为ThreadLocal。 FacesContext的生命周期与ServletContext的生命周期无关。
也许这还不够(听起来你已经走过了这条路),但是你应该能够使用ServletContextListener来做你想做的事情。只需确保对FacesContext的任何调用都保存在JSP的请求线程中。
的web.xml:
<listener>
<listener-class>appobj.MyApplicationContextListener</listener-class>
</listener>
实现:
public class MyApplicationContextListener implements ServletContextListener {
private static final String FOO = "foo";
public void contextInitialized(ServletContextEvent event) {
MyObject myObject = new MyObject();
event.getServletContext().setAttribute(FOO, myObject);
}
public void contextDestroyed(ServletContextEvent event) {
MyObject myObject = (MyObject) event.getServletContext().getAttribute(
FOO);
try {
event.getServletContext().removeAttribute(FOO);
} finally {
myObject.dispose();
}
}
}
您可以通过JSF应用程序范围来解决此对象(如果没有其他变量存在同名,则直接解决):
<f:view>
<h:outputText value="#{applicationScope.foo.value}" />
<h:outputText value="#{foo.value}" />
</f:view>
如果您希望在JSF托管bean中检索对象,可以从ExternalContext获取它:
FacesContext.getCurrentInstance()
.getExternalContext().getApplicationMap().get("foo");
答案 1 :(得分:0)
使用侦听器或加载启动时,请尝试以下操作:http://www.thoughtsabout.net/blog/archives/000033.html
答案 2 :(得分:0)
在JSF 2+中,您可以使用SystemEventListener
来处理它。您可以将其设置为对PostConstructApplicationEvent
执行操作以初始化它。
<system-event-listener>
<system-event-listener-class>
listeners.SystemEventListenerImpl
</system-event-listener-class>
<system-event-class>
javax.faces.event.PostConstructApplicationEvent
</system-event-class>
</system-event-listener>
实现看起来像:
public class SystemEventListenerImpl implements SystemEventListener {
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
Application application = (Application) event.getSource();
//TODO
}
@Override
public boolean isListenerForSource(Object source) {
return (source instanceof Application);
}
}
这样您就可以做更多的事情,而不仅仅是传递一个值。