Listener

  使用Listener不需要关注该类事件是怎样触发的或者怎么调用相应的Listener,只要记住该类事件触发时一定会调用相应地Listener。遵循Servlet规范的服务器完成了相应地工作,开发者只要早Listener里编写相关的代码就行了。

Listener分类:

1,监听对象的创建与销毁

  HttpSessionListener、ServletContextListener、ServletRequestListener分别用于监控session、context、request的创建与销毁。

  以session为例:

public class SessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        // 获得新建的session
        HttpSession session = se.getSession();
        //打印sessionId
        System.out.println(session.getId());
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        // 打印销毁sessionId
        System.out.println(se.getSession().getId());
    }

}

  在web.xml中注册:

      <listener>
              <listener-class>
              com.inspur.filter.replaceText.SessionListener
              </listener-class>
      </listener>

2,监听对象的属性变化

  这类Listener用于监听Session、context、request的属性变化,接口分别为HttpSessionAttributeListener、ServletContextAttributeListener、ServletRequestAttributeListener。当向被监听对象中添加、更新、移除属性时,会分别执行xxxAdded()、xxxReplaced()、xxxRemoved()方法。

public class SessionAttributeListener implements HttpSessionAttributeListener {

    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        //打印session新添加的属性名和属性值
        System.out.println(se.getName()+se.getValue());
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
        //打印session移除的属性名和属性值
        System.out.println(se.getName()+se.getValue());
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
        System.out.println("修改前的属性名和属性值:" + se.getName()+se.getValue());
        System.out.println("修改后的属性名和属性值:" + se.getName()+se.getSession().getAttribute(se.getName()));
    }
}

  在web.xml中注册:

        <listener>
              <listener-class>
              com.inspur.filter.replaceText.SessionAttributeListener
              </listener-class>
      </listener>

3,监听Session内的对象(这个一般用的比较少,不再举例)

  这类Listener用于监控Session内的对象,分别是HttpSessionBindingListener与HttpActivationListener。

  • HttpSessionBindingListener:当对象被放到Session里执行valueBound(HttpSessionBindingEvent event)方法。当对象被从Session里移除时执行valueUnbound(HttpSessionBindingEvent event)方法。
  • HttpActivationListener:服务器关闭时,会将Session里的内容保存到硬盘上,这个过程叫做钝化,此时会执行sessionWillPassivate(HttpSessionEvent se)方法。服务器重新启动时,会将Session内容从硬盘上重新加载,此时会执行sessionDidACTIVATE(HttpSessionEvent se)方法。

踢人小案列

列出所有的在线用户,后台管理者拥有踢人的权利,点击踢人的超链接,该用户就被注销了。

分析

首先,怎么能列出所有的在线用户呢??一般我们在线用户都是用Session来标记的,所有的在线用户就应该用一个容器来装载所有的Session。。

我们监听Session的是否有属性添加(监听Session的属性有添加、修改、删除三个方法。如果监听到Session添加了,那么这个肯定是个在线用户!)。

装载Session的容器应该是在Context里边的【属于全站点】,并且容器应该使用Map集合【待会还要通过用户的名字来把用户踢了】

思路:

  • 写监听器,监听是否有属性添加在Session里边了
  • 写简单的登陆页面。
  • 列出所有的在线用户
  • 实现踢人功能(也就是摧毁Session)

代码

  • 监听器
public class KickPerson implements HttpSessionAttributeListener {

    // Public constructor is required by servlet spec
    public KickPerson() {
    }

    public void attributeAdded(HttpSessionBindingEvent sbe) {

        //得到context对象,看看context对象是否有容器装载Session
        ServletContext context = sbe.getSession().getServletContext();

        //如果没有,就创建一个呗
        Map map = (Map) context.getAttribute("map");
        if (map == null) {
            map = new HashMap();
            context.setAttribute("map", map);
        }

        //---------------------------------------------------------------------------------------
        
        //得到Session属性的值
        Object o = sbe.getValue();

        //判断属性的内容是否是User对象
        if (o instanceof User) {
            User user = (User) o;
            map.put(user.getUsername(), sbe.getSession());
        }
    }

    public void attributeRemoved(HttpSessionBindingEvent sbe) {
      /* This method is called when an attribute
         is removed from a session.
      */
    }

    public void attributeReplaced(HttpSessionBindingEvent sbe) {
      /* This method is invoked when an attibute
         is replaced in a session.
      */
    }
}
  • 登陆页面
<form action="${pageContext.request.contextPath }/LoginServlet" method="post">
    用户名:<input type="text" name="username">
    <input type="submit" value="登陆">
</form>
  • 处理登陆Servlet
        //得到传递过来的数据
        String username = request.getParameter("username");

        User user = new User();
        user.setUsername(username);

        //标记该用户登陆了!
        request.getSession().setAttribute("user", user);

        //提供界面,告诉用户登陆是否成功
        request.setAttribute("message", "恭喜你,登陆成功了!");
        request.getRequestDispatcher("/message.jsp").forward(request, response);
  • 列出在线用户
<c:forEach items="${map}" var="me">

    ${me.key} <a href="${pageContext.request.contextPath}/KickPersonServlet?username=${me.key}">踢了他吧</a>

    <br>
</c:forEach>
  • 处理踢人的Servlet
        String username = request.getParameter("username");

        //得到装载所有的Session的容器
        Map map = (Map) this.getServletContext().getAttribute("map");

        //通过名字得到Session
        HttpSession httpSession = (HttpSession) map.get(username);
        httpSession.invalidate();
        map.remove(username);

        //摧毁完Session后,返回列出在线用户页面
        request.getRequestDispatcher("/listUser.jsp").forward(request, response);
身体是革命的本钱,爱跑步,爱生活!
原文地址:https://www.cnblogs.com/caozx/p/9277103.html