Java监听器

376 阅读8分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

13.监听器

13.1什么是监听器

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

简而言之:

  • 所谓的监听器就是一个能够监听程序内容或者状态是否发生改变的一个Java类
  • 有点类似现实世界中大厦里的火灾警报器

补充讲解:与监听器相关的术语

  • 事件源:指的是被监听对象(汽车)

  • 监听器:指的是监听的对象(报警器)

  • 事件源和监听器绑定:在汽车上安装报警器

  • 事件:指的是事件源对象的改变(踹了汽车一脚)----主要功能获得事件源对象。

13.2.监听器的作用

导读模块:

  • 虽然监听器的作用很强大,但是servlet中并没有相关的实现类
  • 只是有一些接口,而这也恰恰体现出了servlet的灵活性

那么servlet中都提供了哪些监听器呢?

  • 其实servlet中的监听器主要是针对request,session,servletContext开展的
  • 监听器要想起作用则必须要有实现类,而实现类要起作用,则必须要有动作,所谓的动作其实就是事件,所谓的事件就是与之关联的一些类
  • servlet中一共有8个监听器接口,6个事件

13. 3:8个监听器接口和6个事件:

  1. ServletContextListener接口 [接口方法] contextInitialized()与 contextDestroyed() [接收事件] ServletContextEvent [触发场景] 在Container加载Web应用程序时(例如启动 Container之后),会呼叫contextInitialized(),而当容器移除Web应用程序时,会呼叫contextDestroyed ()方法。

  2. ServletContextAttributeListener [接口方法] attributeAdded()、 attributeReplaced()、attributeRemoved() [接收事件] ServletContextAttributeEvent [触发场景] 若有对象加入为application(ServletContext)对象的属性,则会呼叫attributeAdded(),同理在置换属性与移除属性时,会分别呼叫attributeReplaced()、attributeRemoved()。

  3. ServletRequestListener [接口方法] requestInitialized()与 requestDestroyed() [接收事件] RequestEvent [触发场景] 在request(HttpServletRequest)对象建立或被消灭时,会分别呼叫这两个方法。

  4. ServletRequestAttributeListener [接口方法] attributeAdded()、 attributeReplaced()、attributeRemoved() [接收事件] HttpSessionBindingEvent [触发场景] 若有对象加入为request(HttpServletRequest)对象的属性,则会呼叫attributeAdded(),同理在置换属性与移除属性时,会分别呼叫attributeReplaced()、 attributeRemoved()。

  5. HttpSessionListener [接口方法] sessionCreated()与sessionDestroyed () [接收事件] HttpSessionEvent [触发场景] 在session (HttpSession)对象建立或被消灭时,会分别呼叫这两个方法。

  6. HttpSessionActivationListener [接口方法] sessionDidActivate()与 sessionWillPassivate() [接收事件] HttpSessionEvent [触发场景] Activate与Passivate是用于置换对象的动作,当session对象为了资源利用或负载平衡等原因而必须暂时储存至硬盘或其它储存器时(透 过对象序列化),所作的动作称之为Passivate,而硬盘或储存器上的session对象重新加载JVM时所采的动作称之为Activate,所以容 易理解的,sessionDidActivate()与 sessionWillPassivate()分别于Activeate后与将Passivate前呼叫。

  7. HttpSessionAttributeListener [接口方法] attributeAdded()、 attributeReplaced()、attributeRemoved() [接收事件] HttpSessionBindingEvent [触发场景] 若有对象加入为session(HttpSession)对象的属性,则会呼叫attributeAdded(),同理在置换属性与移除属性时,会分别呼叫attributeReplaced()、 attributeRemoved()。

  8. HttpSessionBindingListener [接口方法] valueBound()与valueUnbound() [接收事件] HttpSessionBindingEvent [触发场景] 实现HttpSessionBindingListener接 口的类别,其实例如果被加入至session(HttpSession)对象的属性中,则会呼叫 valueBound(),如果被从session(HttpSession)对象的属性中移除,则会呼叫valueUnbound(),实现 HttpSessionBindingListener接口的类别不需在web.xml中设定。

小结与分类:

备:一共分为三大类

  1. 监听ServletContext、Request、Session对象的创建和销毁,需要在web.xml中配置 ServletContextListener (应用程序、application 上下文 创建和销毁 监听器) ServletRequestListener (request请求对象 创建和销毁 监听器) HttpSessionListener (session 创建和销毁 监听器) 友情提示:这三种是最常用的了......
  2. 监听ServletContext、Request、Session对象属性的变化,需要在web.xml中配置 ServletContextAttributeListener (application、ServletContext 属性变化的一个监听器 ) ServletRequestAttributeListener (Request 属性变化的一个监听器 ) HttpSessionAttributeListener (Session 属性变化的一个监听器)
  3. 监听Session内部的对象,不需要再web.xml中配置 HttpSessionActivationListener (激活)(session内部对象的一个监听,但是不需要再web.xml中配置) HttpSessionBindingListener (捆绑)

2.监听器的作用:

  • 统计在线人数,利用HttpSessionListener

  • 加载初始化信息:利用ServletContextListener

  • 统计网站访问量

  • 实现访问监控

后续的Spring等框架中也要用到

13.4.监听实例

监听器的应用举例--实现统计在线人数

  1. 监听器使用步骤: 1)创建实现类实现需要的HttpSessionListener接口(创建监听器接口的实现类) 2)在web.xml中配置<listener></listener>节点进行声明 3)实现接口中的方法

  2. 统计在线人数示例代码:

package com.turing.manage.listeners;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * @desc   session监听器其目的是为了实现统计在线人数
 * @author Li Ya Hui 
 * @time   2021年6月16日 下午9:59:18
 */
public class SessionListener implements HttpSessionListener {

	//构建无参,
	public SessionListener() {
		System.out.println("session监听器初始化......");
		// TODO Auto-generated constructor stub
	}
	/**
	 * @desc 1. session创建的时候
	 */
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		//1.根据传入的事件对象(HttpSessionEvent)获取Session对象 (事件源对象	(被监听对象))
		System.out.println("session创建的开始------------------------------");
		HttpSession session = se.getSession();
		System.out.println("sessionid:"+session.getId());
		System.out.println("sessionuser"+session.getAttribute("user"));
		
		//2.通过session获取ServletContext对象(application对象 : 全局都起作用的,所以可以将统计的在线总人数的这个变量存放于在这个作用域中)
		ServletContext sc = session.getServletContext();
		
		//3.判断application对象中是否有(已经有人登录上的)值    通过session的数量,在页面上显示人数
		Integer numSession = (Integer) sc.getAttribute("numSession");
		
		//如果数量为0
		if(numSession==null) 
		{
			//session赋值为1
			numSession=new Integer( 1 );
		}
		else {
			//获取登陆前的session 数量值
			int temp = numSession.intValue();
			//将上一次的session数量 + 1 返回给总数量
			numSession = new Integer(temp + 1);
		}
		//4.将数据放入 application 作用域里
		sc.setAttribute("numSession", numSession);
	}
	/**
	 * @desc 2. session销毁的时候
	 */
	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		System.out.println("session销毁的开始");
		//1.根据传入的事件对象(HttpSessionEvent)获取Session对象 (事件源对象	(被监听对象))
				HttpSession session = se.getSession();
				System.out.println("sessionid:"+session.getId());
				System.out.println("sessionuser"+session.getAttribute("user"));
				//2.通过session获取ServletContext对象(application对象 : 全局都起作用的,所以可以将统计的在线总人数的这个变量存放于在这个作用域中)
				ServletContext sc = session.getServletContext();
				
				//3.判断application对象中是否有(已经有人登录上的)值    通过session的数量,在页面上显示人数
				Integer numSession = (Integer) sc.getAttribute("numSession");
				
				//如果数量为0
				if(numSession==null) 
				{
					//session赋值为1
					numSession=new Integer( 0 );
				}
				else {
					//获取登陆前的session 数量值
					int temp = numSession.intValue();
					//将上一次的session数量 + 1 返回给总数量
					numSession = new Integer(temp - 2);
				}
				//4.将数据放入 application 作用域里
				sc.setAttribute("numSession", numSession);
	}
}

监听器的应用举例之--预加载初始化一些数据信息

  1. 监听器使用步骤: 1)创建实现类实现需要的ServletContextListener接口(创建监听器接口的实现类) 2)在web.xml中配置<listener></listener>节点进行声明 3)实现接口中的方法
  2. 预加载初始化一些数据信息 示例代码:
package com.turing.manage.listeners;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * @desc   上下文内容监听器其目的  预加载初始化一些数据信息
 * @author Li Ya Hui 
 * @time   2021年6月17日 上午10:55:23
 */
public class MyServletContextListener implements ServletContextListener {
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("===============servlet服务初始化(也就是tomcat正式启动成功)==================");
		System.out.println("***************1.可以开始预加载一些信息了****************");	 
	    ServletContext context = sce.getServletContext();
	    /**
	     * 1.可以预先加载连库4要素
	     */
	    Map<String, Object> map=new HashMap<String, Object>();
	    map.put("username", "root");
	    map.put("password", "root");
	    map.put("drivername", "com.mysql.jdbc.Driver");
	    map.put("url", "jdbc://..........");
	    context.setAttribute("map", map);
	    /**
	     * 2.也可以在这里实现注入....其实也就是Spring框架核心的注入的原理所在。。。。。(后续讲)
	     */
	}
	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("===============servlet服务销毁(也就是tomcat重新部署)==================");
	}
}

监听器的应用举例之--Request请求监听器记录ip

  1. 监听器使用步骤: 1)创建实现类实现需要的ServletRequestListener接口(创建监听器接口的实现类) 2)在web.xml中配置<listener></listener>节点进行声明 3)实现接口中的方法
  2. Request请求监听器记录ip 示例代码:
package com.turing.manage.listeners;

import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

/**
 * @desc   监听器应用举例之-Request请求监听器
 * @author Li Ya Hui 
 * @time   2021年6月17日 上午11:35:11
 */
public class MyServletRequestListener implements ServletRequestListener {
	/**
	 * @desc 1.请求的初始化
	 * @param sre
	 */
	public void requestDestroyed(ServletRequestEvent sre) {
		//1.通过sre事件获取到事件源
		ServletRequest request = sre.getServletRequest();
		System.out.println("ip:"+request.getRemoteHost()+"开始请求!");
	}
	/**
	 * @desc 2.请求的销毁/结束 
	 */	
	@Override
	public void requestInitialized(ServletRequestEvent sre) {
		//1.通过sre事件获取到事件源
		ServletRequest request = sre.getServletRequest();
		System.out.println("ip:"+request.getRemoteHost()+"结束请求!");
	}
}