当Web应用在Web容器中运行时,应用内部会不断地发生各种事件:如应用被启动,应用被停止,用户session开始,用户session结束,用户请求到达等。通常来说,这些Web事件对开发者是透明的。Servlet API提供了大量的监听器来监听Web应用的内部事件,从而允许当Web内部事件发生时回调事件监听器内的方法。与AWT事件编程完全相似,监听不同Web事件的监听器也不相同。
public class SystemListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
cn.org.yjj.SystemL istener
用于监听Web应用的启动和关闭。该接口包含两个方法:
contextInitialized(ServletContextEvent servletContextEvent):启动Web应用时,系统调用该方法。
contextDestroyed(ServletContextEvent servletContextEvent):停止Web应用时,系统调用该方法。
示例:Web应用启动时获取数据库连接。Listener配置:
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
try {
ServletContext application = servletContextEvent.getServletContext();
String driver = application.getInitParameter("driver");
String url = application.getInitParameter("url");
String username = application.getInitParameter("username");
String pass = application.getInitParameter("pass");
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, username, pass);
application.setAttribute("conn", connection);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
ServletContext application = servletContextEvent.getServletContext();
Connection connection = (Connection) application.getAttribute("conn");
if(connection != null){
try {
connection.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
web.xml配置:
......
driver
com.mysql.jdbc.Driver
......
需要注意的是:Listener获取的是Web应用的配置参数,而不是像Servlet和Filter获取本身的配置参数。
上面示例中整个Web应用都会使用一个数据库连接,性能较差,实际程序中一般会采用初始化DataSource的方式来获取数据库连接。
它用于监听ServletContext(application)范围内属性的变化。
实现该接口的监听器需要实现如下三个方法:
public class AppAttributeListener implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
// 当程序把一个属性存入application范围时触发
}
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
// 把一个属性从application范围删除时触发
}
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
// 把一个属性从application范围替换时触发
}
}
与ServletContext作用域不同,它监听请求和请求范围内的属性变化。示例:
public class ReqListener implements ServletRequestListener, ServletRequestAttributeListener {
@Override
public void attributeAdded(ServletRequestAttributeEvent event) {
ServletRequest request = event.getServletRequest();
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent event) {
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent event) {
}
@Override
public void requestDestroyed(ServletRequestEvent event) {
}
@Override
public void requestInitialized(ServletRequestEvent event) {
HttpServletRequest request = (HttpServletRequest) event.getServletRequest();
}
}
由于实现了ServletRequestListener接口的监听器可以非常方便地监听到每次请求的创建、销毁,因此Web应用可通过实现该接口的监听器来访问该应用的每个请求,从而实现系统日志。
用于监听session的创建和销毁,以及session范围内属性的变化。
public class SessListener implements HttpSessionListener, HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
}
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
}
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
ServletContext context = session.getServletContext();
String sessionId = session.getId();
if(session.isNew()){
String user = (String) session.getAttribute("user");
user = (user == null) ? "游客" : user;
Map online = (Map) context.getAttribute("online");
if(online == null){
online = new HashMap();
}
online.put(sessionId, user);
context.setAttribute("online", online);
}
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
ServletContext context = session.getServletContext();
String sessionId = session.getId();
Map online = (Map)context.getAttribute("online");
if(online != null){
online.remove(sessionId);
}
context.setAttribute("online", online);
}
}
实现HttpSessionListener接口的监听器可以监听每个用户会话的开始和断开,因此应用可以通过该监听器监听系统的在线用户。如果需要监听每个用户停留在哪个页面,本次在线的停留时间,用户的访问IP等信息,则应该考虑定时检查HttpServletRequest来实现,定时任务可以由ServletContextListener来指定。