一、监听器介绍

1.1、监听器的概念

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

1.2、监听器案例——监听window窗口的事件监听器

  1. package com.listener.demo;
  2.  
  3. import java.awt.Frame;
  4. import java.awt.event.WindowEvent;
  5. import java.awt.event.WindowListener;
  6.  
  7. public class Demo1 {
  8.  
  9. /**
  10. * java的事件监听机制
  11. * 1、事件监听涉及到三个组件:事件源、事件对象、事件监听器
  12. * 2、当事件源上发生某一个动作时,它会调用事件监听器的一个方法,并在调用该方法时把事件对象传递进去,
  13. * 开发人员在监听器中通过事件对象,就可以拿到事件源,从而对事件源进行操作。
  14. */
  15. public static void main(String[] args) {
  16.  
  17. Frame f = new Frame();
  18. f.setSize(400, 400);
  19. f.setVisible(true);
  20.  
  21. //注册事件监听器
  22. f.addWindowListener(new WindowListener(){
  23.  
  24. public void windowActivated(WindowEvent e) {
  25.  
  26. }
  27.  
  28. public void windowClosed(WindowEvent e) {
  29.  
  30. }
  31.  
  32. /**
  33. * 当window窗体关闭时就会WindowListener这个监听器监听到,
  34. * 监听器就会调用windowClosing方法处理window窗体关闭时的动作
  35. */
  36. public void windowClosing(WindowEvent e) {
  37. //通过事件对象e来获取事件源对象
  38. Frame f = (Frame) e.getSource();
  39. System.out.println(f+"窗体正在关闭");
  40. f.dispose();
  41. }
  42.  
  43. public void windowDeactivated(WindowEvent e) {
  44.  
  45. }
  46.  
  47. public void windowDeiconified(WindowEvent e) {
  48.  
  49. }
  50.  
  51. public void windowIconified(WindowEvent e) {
  52.  
  53. }
  54.  
  55. public void windowOpened(WindowEvent e) {
  56.  
  57. }
  58. });
  59. }
  60. }

1.3、设计一个可以被别的对象监听的对象

  我们平时做开发的时候,我们是写监听器去监听其他对象,那么我们如果想设计一个对象,让这个对象可以被别的对象监听又该怎么做呢,可以按照严格的事件处理模型来设计一个对象,这个对象就可以被别的对象监听,事件处理模型涉及到三个组件:事件源、事件对象、事件监听器。

  下面我们来按照事件处理模型来设计一个Person对象具体代码如下:

  1. package com.observer;
  2.  
  3. /**
  4. * @ClassName: Person(事件源)
  5. * @Description: 设计一个Person类作为事件源,这个类的对象的行为(比如吃饭、跑步)可以被其他的对象监听
  6. * @author: hdb
  7. * @date: 2017-11-9 20:26:06
  8. *
  9. */
  10. public class Person {
  11. /**
  12. * @Field: listener
  13. * 在Person类中定义一个PersonListener变量来记住传递进来的监听器
  14. */
  15. private PersonListener listener;
  16.  
  17. /**
  18. * @Method: eat
  19. * @Description: 设计Person的行为:吃
  20. * @Anthor:hdb
  21. *
  22. */
  23. public void eat() {
  24. if (listener != null) {
  25. /**
  26. * 调用监听器的doeat方法监听Person类对象eat(吃)这个动作,将事件对象Event传递给doeat方法,
  27. * 事件对象封装了事件源,new Event(this)中的this代表的就是事件源
  28. */
  29. listener.doeat(new Event(this));
  30. }
  31. }
  32.  
  33. /**
  34. * @Method: run
  35. * @Description: 设计Person的行为:跑
  36. * @Anthor:hdb
  37. *
  38. */
  39. public void run() {
  40. if (listener != null) {
  41. /**
  42. * 调用监听器的dorun方法监听Person类对象run(跑)这个动作,将事件对象Event传递给doeat方法,
  43. * 事件对象封装了事件源,new Event(this)中的this代表的就是事件源
  44. */
  45. listener.dorun(new Event(this));
  46. }
  47. }
  48.  
  49. /**
  50. * @Method: registerListener
  51. * @Description: 这个方法是用来注册对Person类对象的行为进行监听的监听器
  52. * @Anthor:hdb
  53. *
  54. * @param listener
  55. */
  56. public void registerListener(PersonListener listener) {
  57. this.listener = listener;
  58. }
  59. }
  60.  
  61. /**
  62. * @ClassName: PersonListener(事件监听器)
  63. * @Description: 设计Person类(事件源)的监听器接口
  64. * @author: hdb
  65. * @date: 2017-11-9 下午9:28:06
  66. *
  67. */
  68. interface PersonListener {
  69.  
  70. /**
  71. * @Method: doeat
  72. * @Description: 这个方法是用来监听Person对象eat(吃)这个行为动作,
  73. * 当实现类实现doeat方法时就可以监听到Person类对象eat(吃)这个动作
  74. * @Anthor:hdb
  75. *
  76. * @param e
  77. */
  78. void doeat(Event e);
  79.  
  80. /**
  81. * @Method: dorun
  82. * @Description: 这个方法是用来监听Person对象run(跑)这个行为动作,
  83. * 当实现类实现dorun方法时就可以监听到Person类对象run(跑)这个动作
  84. * @Anthor:hdb
  85. *
  86. * @param e
  87. */
  88. void dorun(Event e);
  89.  
  90. }
  91.  
  92. /**
  93. * @ClassName: Event(事件对象)
  94. * @Description:设计事件类,用来封装事件源
  95. * @author: hdb
  96. * @date: 2017-11-9 下午9:37:56
  97. *
  98. */
  99. class Event {
  100.  
  101. /**
  102. * @Field: source
  103. * 事件源(Person就是事件源)
  104. */
  105. private Person source;
  106.  
  107. public Event() {
  108.  
  109. }
  110.  
  111. public Event(Person source) {
  112. this.source = source;
  113. }
  114.  
  115. public Person getSource() {
  116. return source;
  117. }
  118.  
  119. public void setSource(Person source) {
  120. this.source = source;
  121. }
  122. }

  经过这样的设计之后,Peron类的对象就是可以被其他对象监听了。测试代码如下:

  1. package com.observer;
  2.  
  3. public class PersonTest {
  4.  
  5. /**
  6. * @Method: main
  7. * @Description: 测试Person类
  8. * @Anthor:hdb
  9. *
  10. * @param args
  11. */
  12. public static void main(String[] args) {
  13. //
  14. Person p = new Person();
  15. //注册监听p对象行为的监听器
  16. p.registerListener(new PersonListener() {
  17. //监听p吃东西这个行为
  18. public void doeat(Event e) {
  19. Person p = e.getSource();
  20. System.out.println(p + "在吃东西");
  21. }
  22. //监听p跑步这个行为
  23. public void dorun(Event e) {
  24. Person p = e.getSource();
  25. System.out.println(p + "在跑步");
  26. }
  27. });
  28. //p在吃东西
  29. p.eat();
  30. //p在跑步
  31. p.run();
  32. }
  33. }

运行结果:

  com.observer.Person@4a5ab2在吃东西
  com.observer.Person@4a5ab2在跑步

二、JavaWeb中的监听器

2.1、基本概念

概念:

  JavaWeb中的监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序中的ServletContext, HttpSession和 ServletRequest等域对象的创建与销毁事件,以及监听这些域对象中的属性发生修改的事件。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。

用途:

  统计在线人数和在线用户,利用HttpSessionLisener

  系统加载时进行信息初始化:利用ServletContextListener

  统计网站访问量

  实现访问监控

2.2、Servlet监听器的分类

  在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别为ServletContextHttpSessionServletRequest这三个域对象
  Servlet规范针对这三个对象上的操作,又把多种类型的监听器划分为三种类型:

  1. 监听域对象自身的创建和销毁的事件监听器。
  2. 监听域对象属性的增加和删除的事件监听器。
  3. 监听绑定到HttpSession域中某个对象的状态的事件监听器。

2.3、监听ServletContext域对象的创建和销毁

  ServletContextListener接口用于监听ServletContext对象的创建和销毁事件。实现了ServletContextListener接口的类都可以对ServletContext对象的创建和销毁进行监听。

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

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

  ServletContext域对象创建和销毁时机:
    创建:服务器启动针对每一个Web应用创建ServletContext
    销毁:服务器关闭前先关闭代表每一个web应用的ServletContext

范例:编写一个MyServletContextListener类,实现ServletContextListener接口,监听ServletContext对象的创建和销毁

  1、编写监听器,代码如下:

  1. package com.web.listener;
  2.  
  3. import javax.servlet.ServletContextEvent;
  4. import javax.servlet.ServletContextListener;
  5.  
  6. /**
  7. * @ClassName: MyServletContextListener
  8. * @Description: MyServletContextListener类实现了ServletContextListener接口,
  9. * 因此可以对ServletContext对象的创建和销毁这两个动作进行监听。
  10. * @author: hdb
  11. * @date: 2017-11-9 下午10:26:16
  12. *
  13. */
  14. public class MyServletContextListener implements ServletContextListener {
  15.  
  16. @Override
  17. public void contextInitialized(ServletContextEvent sce) {
  18. System.out.println("ServletContext对象创建");
  19. }
  20.  
  21. @Override
  22. public void contextDestroyed(ServletContextEvent sce) {
  23. System.out.println("ServletContext对象销毁");
  24. }
  25. }

  2、在web.xml文件中注册监听器

  我们在上面的中讲到,要想监听事件源,那么必须将监听器注册到事件源上才能够实现对事件源的行为动作进行监听,在JavaWeb中,监听的注册是在web.xml文件中进行配置的,如下:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app version="3.0"
  3. xmlns="http://java.sun.com/xml/ns/javaee"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
  6. http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  7. <display-name></display-name>
  8. <welcome-file-list>
  9. <welcome-file>index.jsp</welcome-file>
  10. </welcome-file-list>
  11.  
  12. <!-- 注册针对ServletContext对象进行监听的监听器 -->
  13. <listener>
  14. <description>ServletContextListener监听器</description>
  15. <!--实现了ServletContextListener接口的监听器类 -->
  16. <listener-class>com.web.listener.MyServletContextListener</listener-class>
  17. </listener>
  18.  
  19. </web-app>

  经过这两个步骤,我们就完成了监听器的编写和注册,Web服务器在启动时,就会自动把在web.xml中配置的监听器注册到ServletContext对象上,这样开发好的MyServletContextListener监听器就可以对ServletContext对象进行监听了。

  在Servlet3.0中,监听器的配置可以直接在代码中通过注释来完成,无需在web.xml中再配置。@WebListener //在此注明以下类是监听器

2.4、监听HttpSession域对象的创建和销毁

  HttpSessionListener 接口用于监听HttpSession对象的创建和销毁
  创建一个Session时,激发sessionCreated (HttpSessionEvent se) 方法
  销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se) 方法。

范例:编写一个MyHttpSessionListener类,实现HttpSessionListener接口,监听HttpSession对象的创建和销毁

  1、编写监听器,代码如下:

  1. package com.web.listener;
  2.  
  3. import javax.servlet.http.HttpSessionEvent;
  4. import javax.servlet.http.HttpSessionListener;
  5.  
  6. /**
  7. * @ClassName: MyHttpSessionListener
  8. * @Description: MyHttpSessionListener类实现了HttpSessionListener接口,
  9. * 因此可以对HttpSession对象的创建和销毁这两个动作进行监听。
  10. * @author: hdb
  11. * @date: 2017-11-9 下午11:04:33
  12. *
  13. */
  14. public class MyHttpSessionListener implements HttpSessionListener {
  15.  
  16. @Override
  17. public void sessionCreated(HttpSessionEvent se) {
  18. System.out.println( se.getSession() + "创建了!!");
  19. }
  20.  
  21. /* HttpSession的销毁时机需要在web.xml中进行配置,如下:
  22. * <session-config>
  23. <session-timeout>1</session-timeout>
  24. </session-config>
  25. 这样配置就表示session在1分钟之后就被销毁
  26. */
  27. @Override
  28. public void sessionDestroyed(HttpSessionEvent se) {
  29. System.out.println("session销毁了!!");
  30. }
  31. }

  2、在web.xml文件中注册监听器

  1. <!--注册针对HttpSession对象进行监听的监听器-->
  2. <listener>
  3. <description>HttpSessionListener监听器</description>
  4. <listener-class>com.web.listener.MyHttpSessionListener</listener-class>
  5. </listener>
  6. <!-- 配置HttpSession对象的销毁时机 -->
  7. <session-config>
  8. <!--配置HttpSession对象的1分钟之后销毁 -->
  9. <session-timeout>1</session-timeout>
  10. </session-config>

  当我们访问jsp页面时,HttpSession对象就会创建,此时就可以在HttpSessionListener观察到HttpSession对象的创建过程了,我们可以写一个jsp页面观察HttpSession对象创建的过程。

如下:index.jsp

  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
  2.  
  3. <!DOCTYPE HTML>
  4. <html>
  5. <head>
  6. <title>HttpSessionListener监听器监听HttpSession对象的创建</title>
  7. </head>
  8.  
  9. <body>
  10. 一访问JSP页面,HttpSession就创建了,创建好的Session的Id是:${pageContext.session.id}
  11. </body>
  12. </html>

运行结果如下:

  

2.5、监听ServletRequest域对象的创建和销毁

  ServletRequestListener接口用于监听ServletRequest 对象的创建和销毁
  Request对象被创建时,监听器的requestInitialized(ServletRequestEvent sre)方法将会被调用
  Request对象被销毁时,监听器的requestDestroyed(ServletRequestEvent sre)方法将会被调用

  ServletRequest域对象创建和销毁时机:
    创建:用户每一次访问都会创建request对象
    销毁:当前访问结束,request对象就会销毁

范例:编写一个MyServletRequestListener类,实现ServletRequestListener接口,监听ServletRequest对象的创建和销毁

  1、编写监听器,代码如下:

  1. package com.web.listener;
  2.  
  3. import javax.servlet.ServletRequestEvent;
  4. import javax.servlet.ServletRequestListener;
  5.  
  6. /**
  7. * @ClassName: MyServletRequestListener
  8. * @Description: MyServletRequestListener类实现了ServletRequestListener接口,
  9. * 因此可以对ServletRequest对象的创建和销毁这两个动作进行监听。
  10. * @author: hdb
  11. * @date: 2017-11-9 下午11:50:08
  12. *
  13. */
  14. public class MyServletRequestListener implements ServletRequestListener {
  15.  
  16. @Override
  17. public void requestDestroyed(ServletRequestEvent sre) {
  18. System.out.println(sre.getServletRequest() + "销毁了!!");
  19.  
  20. }
  21.  
  22. @Override
  23. public void requestInitialized(ServletRequestEvent sre) {
  24. System.out.println(sre.getServletRequest() + "创建了!!");
  25. }
  26. }

  2、在web.xml文件中注册监听器

  1. <!--注册针对ServletRequest对象进行监听的监听器-->
  2. <listener>
  3. <description>ServletRequestListener监听器</description>
  4. <listener-class>com.web.listener.MyServletRequestListener</listener-class>
  5. </listener>

测试结果如下:

  

  从运行结果中可以看到,用户每一次访问都会创建request对象,当访问结束后,request对象就会销毁。

2.6、getAttribute与getParameter的区别

  这部分是对JSP的扩展,经常在JSP或者Servlet中获取数据,那么getAttribute与getParameter有什么区别呢?

  1 从获取到数据的来源来说:

  getAttribtue获取到的是web容器中的值,比如:

  我们在Servlet中通过setAttribute设定某个值,这个值存在于容器中,就可以通过getAttribute方法获取;

  getParameter获取到的是通过http传来的值,比如这样一个http请求:

  1. http:localhost:8080/test/test.html?username=xingoo

  还有其他的GET和POST方式,都可以通过getParameter来获取。

  2 从获取到的数据类型来说:

  getAttribute返回的是一个对象,Object。

  getParameter返回的是,前面页面中某个表单或者http后面参数传递的值,是个字符串。

2.7、常用监听器

除了上面监听session建立与销毁的listener外,还有以下几个常用的监听器。

1:监听session属性的增加、移除以及属性值改变的HttpSessionAttributeListener

2:监听web上下文的初始化(服务器已准备好接收请求)与销毁的ServletContextListener

3:监听web上下文属性的增加、删除、属性值变化的ServletContextAttributeListener

4:监听request的创建与销毁的ServletRequestListener

5:监听request的属性的增加、删除、属性值变化的ServletRequestAttributeListener

监听器(Listener)学习(一)的更多相关文章

  1. javaWeb学习总结(11)- 监听器(Listener)学习

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

  2. 监听器(Listener)学习(二)在开发中的常见应用

    监听器在JavaWeb开发中用得比较多,下面说一下监听器(Listener)在开发中的常见应用: 统计当前在线人数 自定义Session扫描器 一.统计当前在线人数 在JavaWeb应用开发中,有时候 ...

  3. 监听器(Listener)学习(二)

    一.监听域对象中属性的变更的监听器 域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信 ...

  4. 深入分析JavaWeb Item39 -- 监听器(Listener)学习进阶

    一.监听域对象中属性的变更的监听器 域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信 ...

  5. javaweb学习总结(四十五)——监听器(Listener)学习二

    一.监听域对象中属性的变更的监听器 域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信 ...

  6. javaweb学习总结(四十四)——监听器(Listener)学习

    一.监听器介绍 1.1.监听器的概念

  7. javaWeb学习总结(11)- 监听器(Listener)学习(2)

    一.监听域对象中属性的变更的监听器 域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信 ...

  8. JavaWeb学习 (二十六)————监听器(Listener)学习(二)

    一.监听域对象中属性的变更的监听器 域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信 ...

  9. javaweb学习总结(四十七)——监听器(Listener)在开发中的应用

    监听器在JavaWeb开发中用得比较多,下面说一下监听器(Listener)在开发中的常见应用 一.统计当前在线人数 在JavaWeb应用开发中,有时候我们需要统计当前在线的用户数,此时就可以使用监听 ...

随机推荐

  1. Kubernetes 删除 namespace

    一. 正常情况情况下的删除: kubectl delete namespace jenkins 二. 如果上面的方法不能删除,且namespace的状态一直显示为Terminating的话 要查看一下 ...

  2. 解决httpclient请求响应压缩文本乱码问题

    最近在调用京东的获取省份接口老是中文乱码,加了utf-8也没有用.最后在httpclient打的日志中有Content-Encoding:gzip信息,最后在请求header里加上: reqHeade ...

  3. logback MDC 使用

    有时候想在logback日志中打印请求IP.流水号这些信息,可以通过MDC(Mapped Diagnostic Contexts)实现: MDC.put("requestNo", ...

  4. git tags 管理

    新建标签: git tag -a V1.1 -m "some thing" (新建标签前请先commit代码) 推送标签: git push --tags (推送标签前请先推送代码 ...

  5. 【Python】学习笔记之列表生成式

    列表生成式 主要用于生成较为复杂的列表 常用用法 >>> [x * x for x in range(5) if x % 3 !=1 ] [0, 4, 9] #返回除以3余数不为1的 ...

  6. 编码转换 Native / UTF-8 / Unicode

    Native/Unicode Native   这是一个例子,this is a example Unicode 这是一个例子,this is a example Native/UTF-8 Nativ ...

  7. zoj4028 LIS,差分约束

    题意:给你以i为结尾的最长上升子序列的值,和每个值的区间范围求可行的a[i] 题解:差分约束,首先满足l[i]<=a[i]<=r[i],可以建一个虚拟节点n+1,那么有a[n+1]-a[i ...

  8. android面试准备一之Activity相关

    1.Activity生命周期 1.1 Activity的4种状态   running/paused/stopped/killed   running:当前Activity正处于运行状态,指的是当前Ac ...

  9. Cannot locate the chosen ObjectFactory implementation: spring

    错误信息: Caused by: Cannot locate the chosen ObjectFactory implementation: spring - [unknown location]  ...

  10. 【Python】测算代码运行时间

    整理自这里和这里 timeit模块 timeit模块定义了接受两个参数的 Timer 类.两个参数都是字符串. 第一个参数是你要计时的语句或者函数. 传递给 Timer 的第二个参数是为第一个参数语句 ...