当上下文初始化时,JSF初始化应用程序bean
我正在构建一个JSF + Facelets Web应用程序,其中一部分是每隔一段时间扫描一次目录并索引任何更改的方法。此方法是处于应用程序范围内的bean的一部分。我已经构建了TimerTask的子类来每X毫秒调用一次该方法。我的问题是让bean初始化。我可以在页面上引用bean,当我进入页面时,bean被初始化,并按照指示工作;我想要的是在Web上下文初始化时初始化bean,以便它不需要页面访问来启动索引方法。谷歌已经展示了一些想要这种功能的人,但除了与Spring集成之外没有真正的解决方案,我真的不想仅仅为了获得这一功能。当上下文初始化时,JSF初始化应用程序bean
我试着玩过两个带有“加载启动时”设置的Servlet,还有一个ServletContextListener让事情继续下去,并且无法获得设置权限,要么是因为没有可用的FacesContext,或者因为我无法从JSF环境中引用bean。
有没有什么办法让Web应用程序启动时初始化JSF bean?
如果你的代码调用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");
使用侦听或时加载的启动,试试这个:http://www.thoughtsabout.net/blog/archives/000033.html
我以前使用过这个技巧,但它不适用于ServletContextListener,因为您没有针对 facesContext = contextFactory的请求/响应。getFacesContext(servletContext,request,response,lifecycle); 如果任何参数为null,则失败。 load-on-startup/init存在同样的问题。 – 2008-11-24 19:47:31
我可能是最好/更容易创建你的类在启动和存储它。然后,当第一次访问jsf bean时,它将检查该类,并使用它或将数据从一个复制到另一个。 – Loki 2008-11-25 22:45:32
在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);
}
}
这将允许你做的不仅仅是简单的传值更。
这最终解决了 - 我错过了“setAttribute”位,使它可以在JSF代码中访问。谢谢! – 2008-12-01 16:44:11