heshao2005 发表于 2018-11-19 12:10:47

Apache Shiro学习笔记(七)Servlet3.0 Listener介绍

鲁春利的工作笔记,好记性不如烂笔头
  

  当Web应用在Web容器中运行时,Web应用内部会不断地发生各种事件:如Web应用被启动、Web应用被停止、用户session开始、用户session结束等。通常这些Web操作对开发者是透明的,但Servlet API也提供了相应的接口来监控这些变化。
  

  当我们要使用Listener时,只需要两个步骤:
① 定义Listener实现类(实现对应的接口)
② 通过Annotation或在web.xml文件中配置Listener
  

  1、实现Listener接口

  不同的Web事件对应的监听器也不同,常用的Web事件监听器接口有如下几个:

[*]  1.1 Servlet Context Events
->ServletContextListener:用于监听Web应用的启动和关闭
->ServletContextAttributeListener:用于监听ServletContext范围(application)内属性的改变

[*]  1.2 Http Session Events
->HttpSessionListener:用于监听用户session的开始和结束
->HttpSessionAttributeListener:用于监听HttpSession范围(session)内属性的改变
->HttpSessionActivationListener:session的passivation是指非活动的session被写入持久设备,activate是反过程。
               一般情况下和HttpSessionBindingListener一起使用。
->HttpSessionBindingListener:实现HttpSessionBindingListener接口的对象被绑定到session时
                触发valueBound事件,解除绑定时触发valueUnbound事件。

[*]  1.3 Servlet Request Events

->ServletRequestListener:用于监听用户请求
->ServletRequestAttributeListener:用于监听ServletRequest范围(request)内属性的改变  一般来说,需要监听哪些Web事件就实现对应接口的方法即可。

  

  2、配置Listener
  实现了Listener类之后,还需要配置Listener,可以选择Annotaion方式或web.xml方式。


[*]  Annotation方式
  只需使用@WebListener修饰Listener实现类即可(要求Servlet3.0以上)

@WebListener
public class MyHttpSessionListener implements HttpSessionListener {......}

[*]  web.xml方式


   
   com.invicme.apps.shiro.listener.XXXListener
  说明:

  在线人数统计网上一般的实现方式是实现HttpSessionListener,监控session的创建(create)和销毁(destroy),但在实际的使用过程中,发现destroy并不及时并且在session.invalidate()的时候还会调用一次sessionCreated()。
package com.invicme.apps.shiro.listener;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
public class OnlineUserBindingListener implements HttpSessionBindingListener {
    String username;
    public OnlineUserBindingListener(String username){
      this.username = username;
    }
    public void valueBound(HttpSessionBindingEvent event) {
      HttpSession session = event.getSession();
      ServletContext application = session.getServletContext();
      // 把用户名放入在线列表
      List onlineUserList = (List) application.getAttribute("onlineUserList");
      // 第一次使用前,需要初始化
      if (onlineUserList == null) {
            onlineUserList = new ArrayList();
            application.setAttribute("onlineUserList", onlineUserList);
      }
      onlineUserList.add(this.username);
    }
    public void valueUnbound(HttpSessionBindingEvent event) {
      HttpSession session = event.getSession();
      ServletContext application = session.getServletContext();
      // 从在线列表中删除用户名
      List onlineUserList = (List) application.getAttribute("onlineUserList");
      onlineUserList.remove(this.username);
      System.out.println(this.username + "退出。");
    }
}  在LoginController中,每次登录成功之后可以执行一次,session.setAttribute("loginUserLS", new OnlineUserBindingListener(username))。
  

  3、Listener示例


[*]  3.1 Servlet Context Events

package com.invicme.apps.shiro.listener.context;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about ServletContext lifecycle changes.
*/
@WebListener
public class MyServletContextListener implements ServletContextListener {
    private static final Logger logger = Logger.getLogger(MyServletContextListener.class);
    public MyServletContextListener() {
      logger.info("MyServletContextListener() was invoke...");
    }
    // Web容器启动的时候执行改方法
    public void contextInitialized(ServletContextEvent sce){
      logger.info("contextInitialized() was invoke.");
    }
    // Web容器reload应用时,首先destroy,然后再initialize
    public void contextDestroyed(ServletContextEvent sce){
      logger.info("contextDestroyed() was invoke.");
    }
}

package com.invicme.apps.shiro.listener.context;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.annotation.WebListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about ServletContext attribute changes.
*/
@WebListener
public class MyServletContextAttributeListener implements ServletContextAttributeListener {
    private static final Logger logger = Logger.getLogger(MyServletContextAttributeListener.class);
    /**
   * Default constructor.
   */
    public MyServletContextAttributeListener() {
      logger.info("MyServletContextAttributeListener() was invoke...");
    }
    // context.setAttribute()
    public void attributeAdded(ServletContextAttributeEvent event){
      logger.info("attributeAdded() was invoke...");
    }
    // context.setAttribute(已设置过的属性)
    public void attributeReplaced(ServletContextAttributeEvent event){
      logger.info("attributeReplaced() was invoke...");
    }
    // context.removeAttribute()
    public void attributeRemoved(ServletContextAttributeEvent event){
      logger.info("attributeRemoved() was invoke...");
    }
}  


[*]  3.2 Http Session Events
package com.invicme.apps.shiro.listener.session;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about HttpSession lifecycle changes.
*/
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
    private static final Logger logger = Logger.getLogger(MyHttpSessionListener.class);
    /**
   * Default constructor.
   */
    public MyHttpSessionListener() {
      logger.info("MyHttpSessionListener() was invoke...");
    }
    // 会话建立(如:request.getSession())
    public void sessionCreated(HttpSessionEvent se){
      logger.info("sessionCreated() was invoke...");
    }
    public void sessionDestroyed(HttpSessionEvent se){
      logger.info("sessionCreated() was invoke...");
    }
}

package com.invicme.apps.shiro.listener.session;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about HttpSession attribute changes.
*/
@WebListener
public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener {
    private static final Logger logger = Logger.getLogger(MyHttpSessionAttributeListener.class);
    /**
   * Default constructor.
   */
    public MyHttpSessionAttributeListener() {
      logger.info("MyHttpSessionAttributeListener() was invoke...");
    }
    // session.setAttribute()
    public void attributeAdded(HttpSessionBindingEvent event){
      logger.info("attributeAdded() was invoke...");
    }
    // session.setAttribute(已经设置过的属性)
    public void attributeReplaced(HttpSessionBindingEvent event){
      logger.info("attributeReplaced() was invoke...");
    }
    // session.removeAttribute()
    public void attributeRemoved(HttpSessionBindingEvent event){
      logger.info("attributeRemoved() was invoke...");
    }
}

package com.invicme.apps.shiro.listener.session;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Causes an object to be notified when it is bound to or unbound from a session.
*/
@WebListener
public class MyHttpSessionBindingListener implements HttpSessionBindingListener {
    private static final Logger logger = Logger.getLogger(MyHttpSessionBindingListener.class);
    /**
   * Default constructor.
   */
    public MyHttpSessionBindingListener() {
      logger.info("MyHttpSessionBindingListener() was invoke...");
    }
    public void valueUnbound(HttpSessionBindingEvent event){
      logger.info("valueUnbound() was invoke...");
    }
    public void valueBound(HttpSessionBindingEvent event){
      logger.info("valueBound() was invoke...");
    }
}  


[*]  3.3 Servlet Request Events
package com.invicme.apps.shiro.listener.request;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about requests coming into and going out of scope of a web application.
*/
@WebListener
public class MyServletRequestListener implements ServletRequestListener {
    private static final Logger logger = Logger.getLogger(MyServletRequestListener.class);
    /**
   * Default constructor.
   */
    public MyServletRequestListener() {
      logger.info("MyServletRequestListener() was invoke...");
    }
    // 每次Http请求都是一个request,方法调用一次
    public void requestInitialized(ServletRequestEvent sre){
      logger.info("requestInitialized() was invoke...");
    }
    // 一次request请求执行完毕
    public void requestDestroyed(ServletRequestEvent sre){
      logger.info("requestDestroyed() was invoke...");
    }
}

package com.invicme.apps.shiro.listener.request;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.annotation.WebListener;
import org.apache.log4j.Logger;
/**
* @author lucl
* Interface for receiving notification events about ServletRequest attribute changes.
*/
@WebListener
public class MyServletRequestAttributeListener implements ServletRequestAttributeListener {
    private static final Logger logger = Logger.getLogger(MyServletRequestAttributeListener.class);
    /**
   * Default constructor.
   */
    public MyServletRequestAttributeListener() {
      logger.info("MyServletRequestAttributeListener() was invoke...");
    }
    public void attributeAdded(ServletRequestAttributeEvent srae){
      logger.info("attributeAdded() was invoke...");
    }
    public void attributeReplaced(ServletRequestAttributeEvent srae){
      logger.info("attributeReplaced() was invoke...");
    }
    public void attributeRemoved(ServletRequestAttributeEvent srae){
      logger.info("attributeRemoved() was invoke...");
    }
}  

  4、Listener监听测试Servlet

package com.invicme.apps.shiro.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
import com.invicme.apps.shiro.listener.session.MyHttpSessionBindingListener;
/**
* @author lucl
*/
@WebServlet("/httpServlet")
public class MyHttpServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static final Logger logger = Logger.getLogger(MyHttpServlet.class);
    public MyHttpServlet() {
      super();
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      doPost(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      // Servlet Context Attribute Event
      {
            ServletContext servletContext = request.getServletContext();
            // attributeAdded
            logger.info("=============servletContext.setAttribute");
            servletContext.setAttribute("sc_name", "sc_value");
            logger.info("=============servletContext.attributeReplaced");
            servletContext.setAttribute("sc_name", "sc_value");
            logger.info("=============servletContext.removeAttribute");
            servletContext.removeAttribute("sc_name");
      }
      // Session Event
      {
            logger.info("=============request.getSession()=>sessionCreated");
            HttpSession session = request.getSession();
            logger.info("=============session.setAttribute()");
            session.setAttribute("s_name", "s_value");
            logger.info("=============session.attributeReplaced()");
            session.setAttribute("s_name", "s_value");
            logger.info("=============session.removeAttribute()");
            session.removeAttribute("s_name");
            // 实现HttpSessionBindingListener接口的对象被绑 定到session时触发valueBound事件,解除绑定时触发valueUnbound事件。
            MyHttpSessionBindingListener bindingListener = new MyHttpSessionBindingListener();
            logger.info("=============session.setAttribute(\"bind\", bindingListener)");
            session.setAttribute("bind", bindingListener);
            logger.info("=============session.removeAttribute(\"bind\")");
            session.removeAttribute("bind");
            logger.info("=============session.invalidate()=>sessionDestroyed");
            session.invalidate();
      }
      // Request Event
      {
            logger.info("=============request.setAttribute()");
            request.setAttribute("r_name", "r_value");
            logger.info("=============request.attributeReplaced()");
            request.setAttribute("r_name", "r_value");
            logger.info("=============request.removeAttribute()");
            request.removeAttribute("r_name");
      }
    }
}  




页: [1]
查看完整版本: Apache Shiro学习笔记(七)Servlet3.0 Listener介绍