JavaWeb中的Listener

应用场景

  1. Web应用启动时,回调方法来启动某些后台程序。
  2. 监听session变化来统计当前在线用户数。
  3. 监听用户请求,统计接口请求次数、用户IP、正在访问的资源以及访问时间等。

Listener介绍

当Web应用在Web容器中运行时,应用内部会不断地发生各种事件:如应用被启动,应用被停止,用户session开始,用户session结束,用户请求到达等。通常来说,这些Web事件对开发者是透明的。Servlet API提供了大量的监听器来监听Web应用的内部事件,从而允许当Web内部事件发生时回调事件监听器内的方法。与AWT事件编程完全相似,监听不同Web事件的监听器也不相同。

Listener使用

  1. 定义Listener实现类。
  2. 在web.xml中配置Listener。
public class SystemListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
    
}

    cn.org.yjj.SystemL istener

Listener类别

ServletContextListener

用于监听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的方式来获取数据库连接。

ServletContextAttributeListener

它用于监听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范围替换时触发
    }
    
}

ServletRequestListener和ServletRequestAttributeListener

与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应用可通过实现该接口的监听器来访问该应用的每个请求,从而实现系统日志。

HttpSessionListener和HttpSessionAttributeListener

用于监听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来指定。


参考资料:《Java EE 企业应用实战 第4版》

你可能感兴趣的:(Java)