上下文初始化时,JSF初始化应用程序范围bean [英] JSF initialize application-scope bean when context initialized
问题描述
我正在构建一个JSF + Facelets Web应用程序,其中一个是每隔一段时间扫描一个目录并为任何更改编制索引的方法。此方法是应用程序范围内的bean的一部分。我已经构建了一个TimerTask的子类来每隔X毫秒调用一次该方法。我的问题是初始化bean。我可以在页面上引用bean,当我转到页面时,bean被初始化,并按照指示工作;我想要的是在初始化Web上下文时初始化bean,这样它就不需要页面访问来启动索引方法。谷歌已经展示了一些想要这个功能的人,但除了与Spring集成之外没有其他真正的解决方案,我真的不想做这个功能。
I'm building a JSF+Facelets web app, one piece of which is a method that scans a directory every so often and indexes any changes. This method is part of a bean which is in application scope. I have built a subclass of TimerTask to call the method every X milliseconds. My problem is getting the bean initialized. I can reference the bean on a page, and when I go to the page, the bean is initialized, and works as directed; what I would like instead is for the bean to be initialized when the web context is initialized, so that it doesn't require a page visit to start the indexing method. Google has shown a few people that want this functionality, but no real solutions outside of integrating with Spring, which I really don't want to do just to get this piece of functionality.
我已经尝试过使用load-on-startup设置的servlet和一个ServletContextListener来使事情继续下去,并且无法正确设置,因为没有'可以使用FacesContext,或者因为我无法从JSF环境中引用bean。
I've tried playing around with both the servlets that have "load-on-startup" set, and a ServletContextListener to get things going, and haven't been able to get the set up right, either because there isn't a FacesContext available, or because I can't reference the bean from the JSF environment.
有没有办法在Web应用程序启动时初始化JSF bean? / p>
Is there any way to get a JSF bean initialized on web app startup?
推荐答案
如果您的代码调用 FacesContext ,它不能在与JSF请求生命周期关联的线程之外工作。为每个请求创建一个FacesContext对象,并在请求结束时处理。您可以通过静态调用是因为它设置为 ThreadLocal 。 FacesContext的生命周期与ServletContext的生命周期无关。
If your code calls FacesContext, it will not work outside a thread associated with a JSF request lifecycle. A FacesContext object is created for every request and disposed at the end of the request. The reason you can fetch it via a static call is because it is set to a ThreadLocal at the start of the request. The lifecycle of a FacesContext bears no relation to that of a ServletContext.
也许这还不够(听起来你已经走过了这条路线),但是你应该能够使用ServletContextListener来做你想要的。只需确保对FacesContext的任何调用都保存在JSP的请求线程中。
Maybe this isn't enough (it sounds like you've already been down this route), but you should be able to use a ServletContextListener to do what you want. Just make sure that any calls to the FacesContext are kept in the JSP's request thread.
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应用程序范围寻址此对象(或者如果没有其他变量存在同名,则直接寻址):
You can address this object via the JSF application scope (or just directly if no other variable exists with the same name):
<f:view>
<h:outputText value="#{applicationScope.foo.value}" />
<h:outputText value="#{foo.value}" />
</f:view>
如果你想在JSF托管bean中检索对象,你可以从 ExternalContext :
If you wish to retrieve the object in a JSF managed bean, you can get it from the ExternalContext:
FacesContext.getCurrentInstance()
.getExternalContext().getApplicationMap().get("foo");
这篇关于上下文初始化时,JSF初始化应用程序范围bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!