監聽器(Listener)(1)
一、監聽器介紹
1.1、監聽器的概念
監聽器是一個專門用於對其他物件身上發生的事件或狀態改變進行監聽和相應處理的物件,當被監視的物件發生情況時,立即採取相應的行動。監聽器其實就是一個實現特定介面的普通java程式,這個程式專門用於監聽另一個java物件的方法呼叫或屬性改變,當被監聽物件發生上述事件後,監聽器某個方法立即被執行。
1.2、監聽器案例——監聽window視窗的事件監聽器
1 package me.gacl.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 me.gacl.observer; 2 3 /** 4 * @ClassName: Person(事件源) 5 * @Description: 設計一個Person類作為事件源,這個類的物件的行為(比如吃飯、跑步)可以被其他的物件監聽 6 * @author: 孤傲蒼狼 7 * @date: 2014-9-9 下午9: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:孤傲蒼狼 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:孤傲蒼狼 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:孤傲蒼狼 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: 孤傲蒼狼 65 * @date: 2014-9-9 下午9:28:06 66 * 67 */ 68 interface PersonListener { 69 70 /** 71 * @Method: doeat 72 * @Description: 這個方法是用來監聽Person物件eat(吃)這個行為動作, 73 * 當實現類實現doeat方法時就可以監聽到Person類物件eat(吃)這個動作 74 * @Anthor:孤傲蒼狼 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:孤傲蒼狼 85 * 86 * @param e 87 */ 88 void dorun(Event e); 89 90 } 91 92 /** 93 * @ClassName: Event(事件物件) 94 * @Description:設計事件類,用來封裝事件源 95 * @author: 孤傲蒼狼 96 * @date: 2014-9-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 me.gacl.observer; 2 3 public class PersonTest { 4 5 /** 6 * @Method: main 7 * @Description: 測試Person類 8 * @Anthor:孤傲蒼狼 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 }
執行結果:
[email protected]在吃東西
[email protected]在跑步
二、JavaWeb中的監聽器
2.1、基本概念
JavaWeb中的監聽器是Servlet規範中定義的一種特殊類,它用於監聽web應用程式中的ServletContext, HttpSession和 ServletRequest等域物件的建立與銷燬事件,以及監聽這些域物件中的屬性發生修改的事件。
2.2、Servlet監聽器的分類
在Servlet規範中定義了多種型別的監聽器,它們用於監聽的事件源分別為ServletContext,HttpSession和ServletRequest這三個域物件 Servlet規範針對這三個物件上的操作,又把多種型別的監聽器劃分為三種類型:
- 監聽域物件自身的建立和銷燬的事件監聽器。
- 監聽域物件中的屬性的增加和刪除的事件監聽器。
- 監聽繫結到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 me.gacl.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: 孤傲蒼狼
11 * @date: 2014-9-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>me.gacl.web.listener.MyServletContextListener</listener-class>
17 </listener>
18
19 </web-app>
經過這兩個步驟,我們就完成了監聽器的編寫和註冊,Web伺服器在啟動時,就會自動把在web.xml中配置的監聽器註冊到ServletContext物件上,這樣開發好的MyServletContextListener監聽器就可以對ServletContext物件進行監聽了。
2.4、監聽HttpSession域物件的建立和銷燬
HttpSessionListener 介面用於監聽HttpSession物件的建立和銷燬 建立一個Session時,激發sessionCreated (HttpSessionEvent se) 方法 銷燬一個Session時,激發sessionDestroyed (HttpSessionEvent se) 方法。
範例:編寫一個MyHttpSessionListener類,實現HttpSessionListener介面,監聽HttpSession物件的建立和銷燬
1、編寫監聽器,程式碼如下:
1 package me.gacl.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: 孤傲蒼狼
11 * @date: 2014-9-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>me.gacl.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 me.gacl.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: 孤傲蒼狼
11 * @date: 2014-9-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>me.gacl.web.listener.MyServletRequestListener</listener-class>
5 </listener>
測試結果如下:
從執行結果中可以看到,使用者每一次訪問都會建立request物件,當訪問結束後,request物件就會銷燬。
以上就是對監聽器的一些簡單講解。