监听器

监听器就是一个实现特定接口的普通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. 爬取拉勾部分求职信息+Bootstrap页面显示

    今天在用python实现爬虫的时候,就想看一下用c#实现同样的功能到底会多出来多少code,结果写着写着干脆把页面也简单的写一个出来,方便调试, 大致流程如下: 1.分析拉勾数据 2.查找拉勾做了哪些 ...

  2. win10 运行sqlplus报错“SP2-1503: 无法初始化 Oracle 调用界面”

    解决方法: 1.临时方案:此时可以以“管理员身份”运行cmd,然后再执行sqlplus就行了. 长久方案: 请看原文:http://blog.csdn.net/bisal/article/detail ...

  3. 回味Python2.7——笔记2

    一.模块 模块是包括 Python 定义和声明的文件.文件名就是模块名加上 .py 后缀.模块的模块名(做为一个字符串)可以由全局变量 __name__ 得到. 1. 模块可以导入其他的模块. 一个( ...

  4. (转)java反射机制及简单工厂模式

    第一步,定义一个接口类 package factory.face; /** * 接口,为了保证返回的对象可以统一用 Product接受 * @author Administrator */ publi ...

  5. hibernate 使用枚举字段的最佳实践

    枚举类虽然很简单,但是却往往是系统中业务逻辑最集中最复杂的地方.本文将会分享我们项目中基于hibernate的枚举类使用规范,包含数据库中枚举列数据类型.注释.枚举列与枚举类的映射等. 一.枚举类定义 ...

  6. 8.Spark SQL

    Spark SQL 1 Why Apache Spark 2 关于Apache Spark 3 如何安装Apache Spark 4 Apache Spark的工作原理 5 spark弹性分布式数据集 ...

  7. [学习笔记] Splay Tree 从入门到放弃

    前几天由于出行计划没有更博QwQ (其实是因为调试死活调不出来了TAT我好菜啊) 伸展树 伸展树(英语:Splay Tree)是一种二叉查找树,它能在O(log n)内完成插入.查找和删除操作.它是由 ...

  8. global,$GLOBALS[' '] 全局, 浮动float跟margin的注意事项

    $a; global只能声明变量为全局,不能赋值,否则报错未定义:global $a; 相对于$GLOBALS['a'],写法是这样的,所有定义过的变量都存在这里: //浮动float跟margin的 ...

  9. JVM学习笔记二:垃圾收集算法

    垃圾回收要解决的问题: 哪些内存需要回收? 线程私有区域不需要回收,如PC.Stack.Native Stack:Java 堆和方法区需要 什么时候回收? 以后的文章解答 如何回收? 首先进行对象存活 ...

  10. AJAX基础_AJAX获取PHP数据

    前言 本篇AJAX基础教程,只讲干货,拒绝废话. 全文通过两个实例来讲解AJAX的基本用法,第1个实例是使用AJAX技术从服务器获取纯文本(HTML)数据, 第2个实例是获取从服务器PHP文件的数据. ...