快速學習JavaWeb中監(jiān)聽器(Listener)的使用方法
一、監(jiān)聽器介紹
1.1、監(jiān)聽器的概念

監(jiān)聽器是一個專門用于對其他對象身上發(fā)生的事件或狀態(tài)改變進行監(jiān)聽和相應處理的對象,當被監(jiān)視的對象發(fā)生情況時,立即采取相應的行動。監(jiān)聽器其實就是一個實現(xiàn)特定接口的普通java程序,這個程序專門用于監(jiān)聽另一個java對象的方法調用或屬性改變,當被監(jiān)聽對象發(fā)生上述事件后,監(jiān)聽器某個方法立即被執(zhí)行。
1.2、監(jiān)聽器案例——監(jiān)聽window窗口的事件監(jiān)聽器
package me.gacl.listener.demo;
import java.awt.Frame;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
public class Demo1 {
/**
*java的事件監(jiān)聽機制
*1、事件監(jiān)聽涉及到三個組件:事件源、事件對象、事件監(jiān)聽器
*2、當事件源上發(fā)生某一個動作時,它會調用事件監(jiān)聽器的一個方法,并在調用該方法時把事件對象傳遞進去,
* 開發(fā)人員在監(jiān)聽器中通過事件對象,就可以拿到事件源,從而對事件源進行操作。
*/
public static void main(String[] args) {
Frame f = new Frame();
f.setSize(400, 400);
f.setVisible(true);
//注冊事件監(jiān)聽器
f.addWindowListener(new WindowListener(){
public void windowActivated(WindowEvent e) {
}
public void windowClosed(WindowEvent e) {
}
/**
* 當window窗體關閉時就會WindowListener這個監(jiān)聽器監(jiān)聽到,
* 監(jiān)聽器就會調用windowClosing方法處理window窗體關閉時的動作
*/
public void windowClosing(WindowEvent e) {
//通過事件對象e來獲取事件源對象
Frame f = (Frame) e.getSource();
System.out.println(f+"窗體正在關閉");
f.dispose();
}
public void windowDeactivated(WindowEvent e) {
}
public void windowDeiconified(WindowEvent e) {
}
public void windowIconified(WindowEvent e) {
}
public void windowOpened(WindowEvent e) {
}
});
}
}
1.3、設計一個可以被別的對象監(jiān)聽的對象
我們平時做開發(fā)的時候,我們是寫監(jiān)聽器去監(jiān)聽其他對象,那么我們如果想設計一個對象,讓這個對象可以被別的對象監(jiān)聽又該怎么做呢,可以按照嚴格的事件處理模型來設計一個對象,這個對象就可以被別的對象監(jiān)聽,事件處理模型涉及到三個組件:事件源、事件對象、事件監(jiān)聽器。
下面我們來按照事件處理模型來設計一個Person對象,具體代碼如下:
package me.gacl.observer;
/**
* @ClassName: Person(事件源)
* @Description: 設計一個Person類作為事件源,這個類的對象的行為(比如吃飯、跑步)可以被其他的對象監(jiān)聽
* @author: 孤傲蒼狼
* @date: 2014-9-9 下午9:26:06
*
*/
public class Person {
/**
* @Field: listener
* 在Person類中定義一個PersonListener變量來記住傳遞進來的監(jiān)聽器
*/
private PersonListener listener;
/**
* @Method: eat
* @Description: 設計Person的行為:吃
* @Anthor:孤傲蒼狼
*
*/
public void eat() {
if (listener != null) {
/**
* 調用監(jiān)聽器的doeat方法監(jiān)聽Person類對象eat(吃)這個動作,將事件對象Event傳遞給doeat方法,
* 事件對象封裝了事件源,new Event(this)中的this代表的就是事件源
*/
listener.doeat(new Event(this));
}
}
/**
* @Method: run
* @Description: 設計Person的行為:跑
* @Anthor:孤傲蒼狼
*
*/
public void run() {
if (listener != null) {
/**
* 調用監(jiān)聽器的dorun方法監(jiān)聽Person類對象run(跑)這個動作,將事件對象Event傳遞給doeat方法,
* 事件對象封裝了事件源,new Event(this)中的this代表的就是事件源
*/
listener.dorun(new Event(this));
}
}
/**
* @Method: registerListener
* @Description: 這個方法是用來注冊對Person類對象的行為進行監(jiān)聽的監(jiān)聽器
* @Anthor:孤傲蒼狼
*
* @param listener
*/
public void registerListener(PersonListener listener) {
this.listener = listener;
}
}
/**
* @ClassName: PersonListener(事件監(jiān)聽器)
* @Description: 設計Person類(事件源)的監(jiān)聽器接口
* @author: 孤傲蒼狼
* @date: 2014-9-9 下午9:28:06
*
*/
interface PersonListener {
/**
* @Method: doeat
* @Description: 這個方法是用來監(jiān)聽Person對象eat(吃)這個行為動作,
* 當實現(xiàn)類實現(xiàn)doeat方法時就可以監(jiān)聽到Person類對象eat(吃)這個動作
* @Anthor:孤傲蒼狼
*
* @param e
*/
void doeat(Event e);
/**
* @Method: dorun
* @Description: 這個方法是用來監(jiān)聽Person對象run(跑)這個行為動作,
* 當實現(xiàn)類實現(xiàn)dorun方法時就可以監(jiān)聽到Person類對象run(跑)這個動作
* @Anthor:孤傲蒼狼
*
* @param e
*/
void dorun(Event e);
}
/**
* @ClassName: Event(事件對象)
* @Description:設計事件類,用來封裝事件源
* @author: 孤傲蒼狼
* @date: 2014-9-9 下午9:37:56
*
*/
class Event {
/**
* @Field: source
* 事件源(Person就是事件源)
*/
private Person source;
public Event() {
}
public Event(Person source) {
this.source = source;
}
public Person getSource() {
return source;
}
public void setSource(Person source) {
this.source = source;
}
}
經過這樣的設計之后,Peron類的對象就是可以被其他對象監(jiān)聽了。測試代碼如下:
package me.gacl.observer;
public class PersonTest {
/**
* @Method: main
* @Description: 測試Person類
* @Anthor:孤傲蒼狼
*
* @param args
*/
public static void main(String[] args) {
//
Person p = new Person();
//注冊監(jiān)聽p對象行為的監(jiān)聽器
p.registerListener(new PersonListener() {
//監(jiān)聽p吃東西這個行為
public void doeat(Event e) {
Person p = e.getSource();
System.out.println(p + "在吃東西");
}
//監(jiān)聽p跑步這個行為
public void dorun(Event e) {
Person p = e.getSource();
System.out.println(p + "在跑步");
}
});
//p在吃東西
p.eat();
//p在跑步
p.run();
}
}
運行結果:
me.gacl.observer.Person@4a5ab2在吃東西
me.gacl.observer.Person@4a5ab2在跑步
二、JavaWeb中的監(jiān)聽器
2.1、基本概念
JavaWeb中的監(jiān)聽器是Servlet規(guī)范中定義的一種特殊類,它用于監(jiān)聽web應用程序中的ServletContext, HttpSession和 ServletRequest等域對象的創(chuàng)建與銷毀事件,以及監(jiān)聽這些域對象中的屬性發(fā)生修改的事件。
2.2、Servlet監(jiān)聽器的分類
在Servlet規(guī)范中定義了多種類型的監(jiān)聽器,它們用于監(jiān)聽的事件源分別為ServletContext,HttpSession和ServletRequest這三個域對象
Servlet規(guī)范針對這三個對象上的操作,又把多種類型的監(jiān)聽器劃分為三種類型:
•監(jiān)聽域對象自身的創(chuàng)建和銷毀的事件監(jiān)聽器。
•監(jiān)聽域對象中的屬性的增加和刪除的事件監(jiān)聽器。
•監(jiān)聽綁定到HttpSession域中的某個對象的狀態(tài)的事件監(jiān)聽器。
2.3、監(jiān)聽ServletContext域對象的創(chuàng)建和銷毀
ServletContextListener接口用于監(jiān)聽ServletContext對象的創(chuàng)建和銷毀事件。實現(xiàn)了ServletContextListener接口的類都可以對ServletContext對象的創(chuàng)建和銷毀進行監(jiān)聽。
•當ServletContext對象被創(chuàng)建時,激發(fā)contextInitialized (ServletContextEvent sce)方法。
•當ServletContext對象被銷毀時,激發(fā)contextDestroyed(ServletContextEvent sce)方法。
•ServletContext域對象創(chuàng)建和銷毀時機:
創(chuàng)建:服務器啟動針對每一個Web應用創(chuàng)建ServletContext
銷毀:服務器關閉前先關閉代表每一個web應用的ServletContext
范例:編寫一個MyServletContextListener類,實現(xiàn)ServletContextListener接口,監(jiān)聽ServletContext對象的創(chuàng)建和銷毀
1、編寫監(jiān)聽器,代碼如下:
package me.gacl.web.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* @ClassName: MyServletContextListener
* @Description: MyServletContextListener類實現(xiàn)了ServletContextListener接口,
* 因此可以對ServletContext對象的創(chuàng)建和銷毀這兩個動作進行監(jiān)聽。
* @author: 孤傲蒼狼
* @date: 2014-9-9 下午10:26:16
*
*/
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext對象創(chuàng)建");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext對象銷毀");
}
}
2、在web.xml文件中注冊監(jiān)聽器
我們在上面的中講到,要想監(jiān)聽事件源,那么必須將監(jiān)聽器注冊到事件源上才能夠實現(xiàn)對事件源的行為動作進行監(jiān)聽,在JavaWeb中,監(jiān)聽的注冊是在web.xml文件中進行配置的,如下:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- 注冊針對ServletContext對象進行監(jiān)聽的監(jiān)聽器 --> <listener> <description>ServletContextListener監(jiān)聽器</description> <!--實現(xiàn)了ServletContextListener接口的監(jiān)聽器類 --> <listener-class>me.gacl.web.listener.MyServletContextListener</listener-class> </listener> </web-app>
經過這兩個步驟,我們就完成了監(jiān)聽器的編寫和注冊,Web服務器在啟動時,就會自動把在web.xml中配置的監(jiān)聽器注冊到ServletContext對象上,這樣開發(fā)好的MyServletContextListener監(jiān)聽器就可以對ServletContext對象進行監(jiān)聽了。
2.4、監(jiān)聽HttpSession域對象的創(chuàng)建和銷毀
HttpSessionListener 接口用于監(jiān)聽HttpSession對象的創(chuàng)建和銷毀
創(chuàng)建一個Session時,激發(fā)sessionCreated (HttpSessionEvent se) 方法
銷毀一個Session時,激發(fā)sessionDestroyed (HttpSessionEvent se) 方法。
范例:編寫一個MyHttpSessionListener類,實現(xiàn)HttpSessionListener接口,監(jiān)聽HttpSession對象的創(chuàng)建和銷毀
1、編寫監(jiān)聽器,代碼如下:
package me.gacl.web.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
/**
* @ClassName: MyHttpSessionListener
* @Description: MyHttpSessionListener類實現(xiàn)了HttpSessionListener接口,
* 因此可以對HttpSession對象的創(chuàng)建和銷毀這兩個動作進行監(jiān)聽。
* @author: 孤傲蒼狼
* @date: 2014-9-9 下午11:04:33
*
*/
public class MyHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println( se.getSession() + "創(chuàng)建了?。?);
}
/* HttpSession的銷毀時機需要在web.xml中進行配置,如下:
* <session-config>
<session-timeout>1</session-timeout>
</session-config>
這樣配置就表示session在1分鐘之后就被銷毀
*/
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("session銷毀了!!");
}
}
2、在web.xml文件中注冊監(jiān)聽器
<!--注冊針對HttpSession對象進行監(jiān)聽的監(jiān)聽器--> <listener> <description>HttpSessionListener監(jiān)聽器</description> <listener-class>me.gacl.web.listener.MyHttpSessionListener</listener-class> </listener> <!-- 配置HttpSession對象的銷毀時機 --> <session-config> <!--配置HttpSession對象的1分鐘之后銷毀 --> <session-timeout>1</session-timeout> </session-config>
當我們訪問jsp頁面時,HttpSession對象就會創(chuàng)建,此時就可以在HttpSessionListener觀察到HttpSession對象的創(chuàng)建過程了,我們可以寫一個jsp頁面觀察HttpSession對象創(chuàng)建的過程。
如下:index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<!DOCTYPE HTML>
<html>
<head>
<title>HttpSessionListener監(jiān)聽器監(jiān)聽HttpSession對象的創(chuàng)建</title>
</head>
<body>
一訪問JSP頁面,HttpSession就創(chuàng)建了,創(chuàng)建好的Session的Id是:${pageContext.session.id}
</body>
</html>
運行結果如下:

2.5、監(jiān)聽ServletRequest域對象的創(chuàng)建和銷毀
ServletRequestListener接口用于監(jiān)聽ServletRequest 對象的創(chuàng)建和銷毀
Request對象被創(chuàng)建時,監(jiān)聽器的requestInitialized(ServletRequestEvent sre)方法將會被調用
Request對象被銷毀時,監(jiān)聽器的requestDestroyed(ServletRequestEvent sre)方法將會被調用
ServletRequest域對象創(chuàng)建和銷毀時機:
創(chuàng)建:用戶每一次訪問都會創(chuàng)建request對象
銷毀:當前訪問結束,request對象就會銷毀
范例:編寫一個MyServletRequestListener類,實現(xiàn)ServletRequestListener接口,監(jiān)聽ServletRequest對象的創(chuàng)建和銷毀
1、編寫監(jiān)聽器,代碼如下:
package me.gacl.web.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
/**
* @ClassName: MyServletRequestListener
* @Description: MyServletRequestListener類實現(xiàn)了ServletRequestListener接口,
* 因此可以對ServletRequest對象的創(chuàng)建和銷毀這兩個動作進行監(jiān)聽。
* @author: 孤傲蒼狼
* @date: 2014-9-9 下午11:50:08
*
*/
public class MyServletRequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println(sre.getServletRequest() + "銷毀了??!");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println(sre.getServletRequest() + "創(chuàng)建了??!");
}
}
2、在web.xml文件中注冊監(jiān)聽器
<!--注冊針對ServletRequest對象進行監(jiān)聽的監(jiān)聽器-->
<listener>
<description>ServletRequestListener監(jiān)聽器</description>
<listener-class>me.gacl.web.listener.MyServletRequestListener</listener-class>
</listener>
測試結果如下:

從運行結果中可以看到,用戶每一次訪問都會創(chuàng)建request對象,當訪問結束后,request對象就會銷毀。
以上就是對監(jiān)聽器的一些簡單講解。
相關文章
IntelliJ IDEA的數據庫管理工具實在太方便了(推薦)
這篇文章主要介紹了IntelliJ IDEA的數據庫管理工具實在太方便了,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09
SpringBoot使用WebSocket實現(xiàn)向前端推送消息功能
WebSocket協(xié)議是基于TCP的一種新的網絡協(xié)議,它實現(xiàn)了瀏覽器與服務器全雙工(full-duplex)通信——允許服務器主動發(fā)送信息給客戶端,本文給大家介紹了SpringBoot使用WebSocket實現(xiàn)向前端推送消息功能,需要的朋友可以參考下2024-05-05
為什么在foreach循環(huán)中JAVA集合不能添加或刪除元素
今天給大家?guī)淼奈恼率顷P于Java的相關知識,文章圍繞著為什么在foreach循環(huán)中JAVA集合不能添加或刪除元素展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下2021-06-06
Java SSM框架(Spring+SpringMVC+MyBatis)搭建過程
最近一段時間搭建了ssm環(huán)境,并測試了幾個小項目,下面小編通過圖文并茂的形式給大家分享Java SSM框架(Spring+SpringMVC+MyBatis)搭建過程,需要的朋友參考下吧2017-11-11
SpringBoot+log4j2.xml使用application.yml屬性值問題
這篇文章主要介紹了SpringBoot+log4j2.xml使用application.yml屬性值問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12

