监听器

监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。

Servlet监听器

在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别为 ServletContext, HttpSessionServletRequest 这三个域对象。

Servlet规范针对这三个对象上的操作,又把这多种类型的监听器划分为三种类型。

  • 监听三个域对象创建和销毁的事件监听器
  • 监听域对象中属性的增加和删除的事件监听器
  • 监听绑定到 HttpSession 域中的某个对象的状态的事件监听器。

编写监听器

和编写其它事件监听器一样,编写servlet监听器也需要实现一个特定的接口,并针对相应动作覆盖接口中的相应方法。

和其它事件监听器略有不同的是,servlet监听器的注册不是直接注册在事件源上,而是由WEB容器负责注册,开发人员只需在web.xml文件中使用<listener>标签配置好监听器,web容器就会自动把监听器注册到事件源中。

一个 web.xml 文件中可以配置多个 Servlet 事件监听器,web 服务器按照它们在 web.xml 文件中的注册顺序来加载和注册这些 Serlvet 事件监听器。

ServletContext监听器

ServletContextListener 接口用于监听 ServletContext 对象的创建和销毁事件。

当 ServletContext 对象被创建时,激发contextInitialized (ServletContextEvent sce)方法

当 ServletContext 对象被销毁时,激发contextDestroyed(ServletContextEvent sce)方法。

servletContext域对象何时创建和销毁:

  • 创建:服务器启动针对每一个web应用创建servletcontext
  • 销毁:服务器关闭前先关闭代表每一个web应用的servletContext
 package com.hanqi.listener;

 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;

 public class TestApplicationListener implements ServletContextListener {

     @Override
     public void contextDestroyed(ServletContextEvent arg0) {
         System.out.println("application对象销毁");
     }

     @Override
     public void contextInitialized(ServletContextEvent arg0) {
         System.out.println("创建application对象");
     }
 }

访问时会在控制台打印“创建application对象”

HttpSession监听器

HttpSessionListener接口用于监听HttpSession的创建和销毁

创建一个Session时,sessionCreated(HttpSessionEvent se) 方法将会被调用。

销毁一个Session时,sessionDestroyed (HttpSessionEvent se) 方法将会被调用。

Session域对象创建和销毁的时机创建:用户每一次访问时,服务器创建session

  • 销毁:如果用户的session 30分钟没有使用,服务器就会销毁session,我们在web.xml里面也可以配置session失效时间

ServletRequest 监听器

ServletRequestListener 接口用于监听ServletRequest 对象的创建和销毁。

Request 对象被创建时,监听器的requestInitialized方法将会被调用。

Request对象被销毁时,监听器的requestDestroyed方法将会被调用。

servletRequest域对象创建和销毁的时机:

  • 创建:用户每一次访问,都会创建一个reqeust
  • 销毁:当前访问结束,request对象就会销毁

当向被监听器对象中增加一个属性时,web容器就调用事件监听器的 attributeAdded 方法进行相应,这个方法接受一个事件类型的参数,监听器可以通过这个参数来获得正在增加属性的域对象和被保存到域中的属性对象

各个域属性监听器中的完整语法定义为:

  • public void attributeAdded(ServletContextAttributeEvent scae)
  • public void attributeAdded (HttpSessionBindingEvent  hsbe)
  • public void attributeAdded(ServletRequestAttributeEvent srae)

监听三个域的属性变化

Servlet规范定义了监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信息事件的监听器。

这三个监听器接口分别是ServletContextAttributeListener, HttpSessionAttributeListener ServletRequestAttributeListener

这三个接口中都定义了三个方法来处理被监听对象中的属性的增加,删除和替换的事件,同一个事件在这三个接口中对应的方法名称完全相同,只是接受的参数类型不同。

当向被监听器对象中增加一个属性时,web容器就调用事件监听器的 attributeAdded 方法进行相应,这个方法接受一个事件类型的参数,监听器可以通过这个参数来获得正在增加属性的域对象和被保存到域中的属性对象

各个域属性监听器中的完整语法定义为:

  • public void attributeAdded(ServletContextAttributeEvent scae)
  • public void attributeAdded (HttpSessionBindingEvent  hsbe)
  • public void attributeAdded(ServletRequestAttributeEvent srae)

当删除被监听对象中的一个属性时,web 容器调用事件监听器的这个方法进行相应

各个域属性监听器中的完整语法定义为:

  • public void attributeRemoved(ServletContextAttributeEvent scae)
  • public void attributeRemoved (HttpSessionBindingEvent  hsbe)
  • public void attributeRemoved (ServletRequestAttributeEvent srae)

当监听器的域对象中的某个属性被替换时,web容器调用事件监听器的这个方法进行相应

各个域属性监听器中的完整语法定义为:

  • public void attributeReplaced(ServletContextAttributeEvent scae)
  • public void attributeReplaced (HttpSessionBindingEvent  hsbe)
  • public void attributeReplaced (ServletRequestAttributeEvent srae)

例子:

 package com.hanqi.listener.attr;

 import javax.servlet.ServletRequestAttributeEvent;
 import javax.servlet.ServletRequestAttributeListener;

 public class TestRequestAttributeListener implements ServletRequestAttributeListener {

     @Override
     public void attributeAdded(ServletRequestAttributeEvent arg0) {
         System.out.println("request对象添加属性");
     }

     @Override
     public void attributeRemoved(ServletRequestAttributeEvent arg0) {
         System.out.println("移除request属性");
     }

     @Override
     public void attributeReplaced(ServletRequestAttributeEvent arg0) {
         System.out.println("替换request属性");
     }

 }
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
request.setAttribute("hanqi", "淄博汉企");//设置request属性
request.removeAttribute("hanqi");移除request属性

session.getCreationTime();//获取session的创建时间

%>
<h1>首页</h1>
<hr>
当前在线人数: <%=application.getAttribute("userCount") %>
<hr>
用户列表:
User [sessionid, session创建时间]
</body>
</html>

应用:统计在线用户数量和用户信息

 package com.util;

 import java.util.Date;

 public class User {
     private String sid;
     private Date stime;

     public String getSid() {
         return sid;
     }
     public void setSid(String sid) {
         this.sid = sid;
     }
     public Date getStime() {
         return stime;
     }
     public void setStime(Date stime) {
         this.stime = stime;
     }
     @Override
     public String toString() {
         return "User :sid=" + sid + ", stime=" + stime + "|";
     }
 }
 package com.listener;

 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.Iterator;

 import javax.servlet.annotation.WebListener;
 import javax.servlet.http.HttpSession;
 import javax.servlet.http.HttpSessionEvent;
 import javax.servlet.http.HttpSessionListener;

 import com.util.User;

 /**
  * Application Lifecycle Listener implementation class SessionListener
  *
  */
 @WebListener
 public class SessionListener implements HttpSessionListener {

     private int userCount;//记录在线人数
     private ArrayList<User> userList;//记录在线人的信息
     /**
      * Default constructor.
      */
     public SessionListener() {
         // TODO Auto-generated constructor stub
     }

     /**
      * @see HttpSessionListener#sessionCreated(HttpSessionEvent)
      */
     //session创建时的方法
     public void sessionCreated(HttpSessionEvent sessionEvent)  {
          // TODO Auto-generated method stub
         userCount++;//用户每一次访问时,服务器创建session,用户数量+1
         if(userList==null) {
             userList = new ArrayList<User>();
         }
         //获取HttpSession,便于显示,不用每一次都调用
         HttpSession session = sessionEvent.getSession();

         String sessionid = session.getId();//获取唯一ID
         long stime = session.getCreationTime();//获取创建时间
         //调用方法查看是不是已经存在的用户,如果不存在,新建用户存入信息,加到集合中
         if(!checkUsersSession(sessionid, userList)) {
             User u = new User();
             u.setStime(new Date(stime));
             u.setSid(sessionid);
             userList.add(u);
         }
         //设置session属性,在线人数和在线信息
         session.getServletContext().setAttribute("userCount", userCount);
         session.getServletContext().setAttribute("userList", userList);
     }

     private boolean checkUsersSession(String sessionid, ArrayList<User> userList2) {
         //查看是不是已经存在的用户,遍历集合,如果集合中有某个元素的id等于传入的id,返回true
         for(User u : userList2) {
             if(u.getSid().equals(sessionid)) {
                 return true;
             }
         }
         return false;
     }

     /**
      * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
      */
     //session销毁时的方法
     public void sessionDestroyed(HttpSessionEvent sessionEvent)  {
         //用户下线,人数-1
         userCount--;
         HttpSession session = sessionEvent.getSession();    

         String sessionid = session.getId();
         System.out.println(sessionid + "的用户下线");
         //获取销毁的用户的sessionid,在从集合中找到,移除
         if(checkUsersSession(sessionid, userList)) {
             Iterator<User> iter = userList.iterator();
             while(iter.hasNext()) {
                 User u = iter.next();
                 if(u.getSid().equals(sessionid)) {
                     iter.remove();
                 }
             }
         }
         session.getServletContext().setAttribute("userCount", userCount);
         session.getServletContext().setAttribute("userList", userList);
     }
 }
 <%@ page language="java" contentType="text/html; charset=utf-8"
     pageEncoding="utf-8" import="java.util.ArrayList,com.util.User"%>
 <%@ page import="java.util.*" %>
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <title>Insert title here</title>
 </head>
 <body>

 当前在线人数: <%=application.getAttribute("userCount") %>
 <hr>
 在线用户列表:<br>
 <%
 List<User> userList = (List<User>)application.getAttribute("userList");//获取application对象,用户信息集合
 if(userList!=null) {//如果集合不为空,遍历显示
     for(User u : userList) {
         out.print(u+"<br>");
     }
 }
 %>
 </body>
 </html> 

尝试加一个踢人推出的功能

JavaWeb(六)Listener监听器的更多相关文章

  1. JavaWeb之Listener监听器

    监听在Java体系中运用的很广泛,在安卓开发.JavaWeb开发中到处存在,在其他语言也有类似的,如果有了解过设计模式那很容易理解实现的原理.不过对于开发者来说,使用观察者模式只需实现相应的接口就好, ...

  2. 转-JavaWeb三大组件之Listener监听器

    JavaWeb三大组件之Listener监听器一.概述1,它是一个接口,内容由我们来实现 2,它需要注册,例如注册在按钮上 3,监听器中的方法,会在特殊事件发生时被调用 二.JavaWeb中的监听器1 ...

  3. javaweb学习总结—监听器(Listener)

    监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动.监听器其实就是一个实现特定接口的普通java程序,这个程序专门用于监听另一 ...

  4. Listener监听器与Filter过滤器

    1.Listener     [1]监听器简介         > Listener是JavaWeb的三大组件之一,Servlet.Filter.Listener         > Li ...

  5. 第16 天 JavaWEB过滤器和监听器技术

    Day16 JavaWEB过滤器和监听器技术 复习: 1.大结果集分页mysql的实现,是使用那个关键字,从user表中取第一页的数据,长度为10,sql语句怎么写? 2.分页查询的起始位置(star ...

  6. 超全面的JavaWeb笔记day20<监听器&国际化>

    JavaWeb监听器 三大组件: l Servlet l Listener l Filter Listener:监听器 1. 初次相见:AWT 2. 二次相见:SAX 监听器: l 它是一个接口,内容 ...

  7. JavaWEB过滤器和监听器技术

    过滤器介绍 什么是过滤器 生活中的例子: 滤水器,口罩,杯子上滤网,渔网 生活中的过滤器:留下我们想要的,排除,我们不想要的. 高考: 只有分数够高的同学才能进入理想的大学.有一部分同学被拦截在大学之 ...

  8. JavaWeb——过滤器及监听器

    什么是过滤器? 过滤器示意图 Filter是如何实现拦截的? Filter的生命周期 Filter的创建 Filter的销毁 FilterConfig接口 Servlet过滤器有关接口 过滤器配置 F ...

  9. .jsp文件的使用和理解以及一些小练习和Listener监听器

    什么是 jsp,它有什么用? jsp 的全换是 java server pages.Java 的服务器页面.jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据.因为 Servle ...

  10. 十:JavaWeb中的监听器(一)

    2.1.基本概念 JavaWeb中的监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序中的ServletContext, HttpSession和 ServletRequest等域 ...

随机推荐

  1. JavaBean规范

    JavaBean规范 (1)JavaBean 类必须是一个公共类,并将其访问属性设置为 public  ,如: public class user{ …}(2)JavaBean 类必须有一个空的构造函 ...

  2. Java后端开发书架

    本人摘录于江南白衣文章,文章地址:http://calvin1978.blogcn.com/articles/javabookshelf.html 书架主要针对Java后端开发. 3.0版把一些后来买 ...

  3. jfinal框架新手使用之路及开发心得

    从接触jfinal这个框架到现在差不多也有一个的时间了,因为之前接触的都是像spring ,springMVC,mybatis,struts2,hibernate这种传统,大多数公司都在用的这种框架. ...

  4. input复选框操作的部分高频率使用代码

    1. 获取单个checkbox选中项(三种写法): $("input:checkbox:checked").val() 或者 $("input:[type='checkb ...

  5. STF,docker学习资料整理

  6. 一步一步学习Vue(六)

    本篇继续介绍vue-router,我们需要要完成这样个demo:<分页显示文章列表>:这里我们以博客园首页列表为例简化处理: 按照上图框选所示,简单分为蓝色部分文章组件(ArticleIt ...

  7. Swift学习之元组(Tuple)

    定义 元组是由若干个类型的数据组成,组成元组的数据叫做元素,每个元素的类型都可以是任意的. 用法一 let tuples1 = ("Hello", "World" ...

  8. keilc 4 编译出现的几个错误…

    原文地址:keilc 4 编译出现的几个错误解决作者:黑子     今天安装了keilc4,因为项目用到,所以把遇到的几个编译错误解决方法说说,第一次写东西不知道写啥!!    一  第一个是错误提示 ...

  9. 带你快速进入.net core的世界

    [申明]:本人.NET Core小白.Linux小白.MySql小白.nginx小白.而今天要说是让你精通Linux ... 的开机与关机.nginx安装与部署.Core的Hello World .. ...

  10. 小明历险记:规则引擎drools教程一

    小明是一家互联网公司的软件工程师,他们公司为了吸引新用户经常会搞活动,小明常常为了做活动加班加点很烦躁,这不今天呀又来了一个活动需求,我们大家一起帮他看看. 小明的烦恼 活动规则是根据用户购买订单的金 ...