我们正在使用 ApplicationListener 加载一些计时器库,这些库将对一些 bean 进行常规后台工作。然而,在 applicationCreated 我们似乎无法通过 ApplicationEx 对象找到进入 ServletContext 的方法。有很多不推荐使用的方法似乎会有所帮助。有谁知道在 applicationCreated 方法期间如何从 ApplicationEx 遍历 FacesContext 或外部 ServletContext ?
2 回答
似乎没有办法从 ApplicationEx 获取 FacesContext 或 ServletContext。
ServletContextListener在 Web 应用程序初始化时提供 ServletContext,但不幸的是,XPages 不支持这种侦听器。
那么,ApplicationListener 和应用程序范围的托管 bean 的组合呢?
首先,ApplicationListener 将启动。然后,如果在用户可以首先调用的每个页面的 beforePageLoad 事件中“调用”托管 bean,它将被实例化。此时
,托管 bean 能够通过以下方式获取 ApplicationListener 对象
(ApplicationEx)(FacesContext.getCurrentInstance().getApplication()).getApplicationListeners()
并且可以在 ApplicationListener 中运行一个方法来获取 FacesContext、ExternalContext 和 bean。ApplicationListener 可以在 FacesContext/ExternalContext 的帮助下启动所有操作(例如计时器库),并将上下文和/或 bean 作为字段保存在 ApplicationListener 对象中。在 applicationDestroyed() 时,仍然可以使用上下文或“关闭”托管 bean。
这是一个例子:
应用程序监听器“我的应用程序监听器”
package com.knutherrmann.listener;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import com.ibm.xsp.application.ApplicationEx;
import com.ibm.xsp.application.events.ApplicationListener;
public class MyApplicationListener implements ApplicationListener {
private FacesContext facesContext;
private ExternalContext externalContext;
private AppBean app;
public void applicationCreated(ApplicationEx arg0) {
System.out.println("applicationCreated(" + arg0.getApplicationId() + ") in MyApplicationListener");
}
public void applicationDestroyed(ApplicationEx arg0) {
System.out.println("applicationDestroyed(" + arg0.getApplicationId() + ") in MyApplicationListener");
System.out.println("...FacesContext: " + facesContext);
System.out.println("...ExternalContext: " + externalContext);
System.out.println("...AppBean: " + app);
app.stop();
}
public void initContext(AppBean app) {
facesContext = FacesContext.getCurrentInstance();
externalContext = facesContext.getExternalContext();
this.app = app;
System.out.println("initContext() in MyApplicationListener");
System.out.println("...FacesContext: " + facesContext);
System.out.println("...ExternalContext: " + externalContext);
System.out.println("...AppBean: " + app);
}
}
应用程序范围的托管 bean“app”作为类“AppBean”的实例
package com.knutherrmann.listener;
import java.io.Serializable;
import javax.faces.context.FacesContext;
import com.ibm.xsp.application.ApplicationEx;
import com.ibm.xsp.application.events.ApplicationListener;
public class AppBean implements Serializable {
private static final long serialVersionUID = 1L;
public AppBean() {
ApplicationEx app = (ApplicationEx) FacesContext.getCurrentInstance().getApplication();
for (ApplicationListener listener : app.getApplicationListeners()) {
if (listener instanceof MyApplicationListener) {
MyApplicationListener myApplicationListener = (MyApplicationListener) listener;
myApplicationListener.initContext(this);
}
}
}
public void start() {
}
public void stop() {
System.out.println("AppBean stopped");
}
}
XPage
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
beforePageLoad="#{app.start}">
Test MyApplicationListener and AppBean
</xp:view>
服务器控制台的输出
07:23:44 HTTP JVM: applicationCreated(32) in MyApplicationListener
07:23:44 HTTP JVM: initContext() in MyApplicationListener
07:23:44 HTTP JVM: ...FacesContext: com.ibm.xsp.domino.context.DominoFacesContext@f850f85
07:23:44 HTTP JVM: ...ExternalContext: com.ibm.xsp.domino.context.DominoExternalContext@13891389
07:23:44 HTTP JVM: ...AppBean: com.knutherrmann.listener.AppBean@22c522c5
07:54:06 HTTP JVM: applicationDestroyed(32) in MyApplicationListener
07:54:06 HTTP JVM: ...FacesContext: com.ibm.xsp.domino.context.DominoFacesContext@f850f85
07:54:06 HTTP JVM: ...ExternalContext: com.ibm.xsp.domino.context.DominoExternalContext@13891389
07:54:06 HTTP JVM: ...AppBean: com.knutherrmann.listener.AppBean@22c522c5
07:54:06 HTTP JVM: AppBean stopped
我们使用服务器的预加载 xpage 功能 ( bit.ly/10rfvEs ),但这不会创建会话,因此永远不会有 FacesContext(获取当前实例返回 null)。所以我们做了一些技巧来打开一个从监听器返回到应用程序的链接,然后创建我们需要的第一个会话和应用程序范围。