监听器

监听器就是一个实现特定接口的普通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. 关于TRIM的优化技巧

    背景 今天在论坛中,看到有人在问一个千万级别表查询的优化.一个简单的查询几分钟.语句如下 SELECT  work_date ,        major ,        style ,      ...

  2. Android创建窗口(一)创建应用窗口

    所谓的窗口(Window)就是一个显示在手机屏幕上可视化视图的一片区域.在Android中窗口是一个抽象的概念,每一个Activity就对应着一个窗口,而所有的窗口都是由视图(View)来呈现,而我们 ...

  3. curl学习之curl_setopt参数设置大总结

    CURL函数库里最重要的函数是curl_setopt(),它可以通过设定CURL函数库定义的选项来定制HTTP请求使用方法:bool curl_setopt (int ch, string optio ...

  4. YAML文件解析

    YAML是“另一种标记语言”的外语缩写,YAML 是一种比JSON(json多层次{ 与 [ 会被搞晕的)更直观的表现形式,展示上更易查错和关系描述.因为不需要一个专业工具就可以排查正确性.YAML目 ...

  5. ubuntu的/etc/modules内核模块文件

    /etc/modules: 内核模块文件,里面列出的模块会在系统启动时自动加载. /etc/modprobe.d: 存放禁止加载或者加载内核模块脚本的目录. 以下是我增加netfilter模块是的流程 ...

  6. AdPlayBanner:功能丰富、一键式使用的图片轮播插件

    AdPlayBanner:功能丰富.一键式使用的图片轮播插件 AdPlayBanner是一个Android平台基于ViewPager实现的轮播图插件,主要用以自动或者手动地播放轮播图,提供了Fresc ...

  7. Jersey实现Restful服务

    jersey 是基于Java的一个轻量级RESTful风格的Web Services框架.以下我基于IDEA实现Restful完整Demo. 1.创建maven-web工程,后面就是正常的maven工 ...

  8. ASP.NET 导出excel文件出现乱码的解决办法

    string html =TABLE ;//<table>标签,可以是多张表string modified = Regex.Replace(html, "<table &g ...

  9. linux--软件包管理工具

    linux平台软件包管理: RPM/DPKG 两大阵营简介 在 GNU/Linux( 以下简称 Linux) 操作系统中,RPM 和 DPKG 为最常见的两类软件包管理工具,他们分别应用于基于 RPM ...

  10. [HEOI2015]兔子与樱花 树规+贪心

    鬼能想到是个贪心.明明觉得是树规啊..又完美爆零.. 从叶子节点往上更新,能保证最优解(这块想了半天). 证明:当你的子树上有能删的点而你不删时,可能会对子树的根节点有利,最好的情况是使子树根节点由不 ...