監(jiān)聽(tīng)器

監(jiān)聽(tīng)器

本文包括:

1、Listener簡(jiǎn)介

2吊履、Servlet監(jiān)聽(tīng)器

3寨典、監(jiān)聽(tīng)三個(gè)域?qū)ο髣?chuàng)建和銷毀的事件監(jiān)聽(tīng)器

4、監(jiān)聽(tīng)三個(gè)域?qū)ο蟮膶傩?Attribute)的變化的事件監(jiān)聽(tīng)器

5卦尊、監(jiān)聽(tīng)綁定到 HttpSession 域中的某個(gè)對(duì)象的狀態(tài)的事件監(jiān)聽(tīng)器

1、Listener簡(jiǎn)介

  • Listener(監(jiān)聽(tīng)器)就是一個(gè)實(shí)現(xiàn)特定接口的普通java程序舌厨,這個(gè)程序?qū)iT用于監(jiān)聽(tīng)另一個(gè)java對(duì)象的方法調(diào)用或?qū)傩愿淖兤袢矗?dāng)被監(jiān)聽(tīng)對(duì)象發(fā)生上述事件后,監(jiān)聽(tīng)器某個(gè)方法將立即被執(zhí)行邓线。
  • 為了加深理解淌友,自定義監(jiān)聽(tīng)器來(lái)練練手,假設(shè)現(xiàn)在有個(gè)體重100的人要吃飯了骇陈,要監(jiān)聽(tīng)他吃飯的動(dòng)作震庭,捕捉到了之后再打印它的體重,具體思路如下你雌;

    1. 事件源類:

      public class Person {
           private String name;
           private int weight;// 體重
           public String getName() {
               return name;
           }
       
           public void setName(String name) {
               this.name = name;
           }
       
           public int getWeight() {
               return weight;
           }
       
           public void setWeight(int weight) {
               this.weight = weight;
           }
       }
      
    2. 監(jiān)聽(tīng)器接口:

       public interface PersonListener {
           public void personeating(PersonEvent event);// 監(jiān)聽(tīng)方法器联,需要一個(gè)事件對(duì)象作為參數(shù)
       }
      
    3. 事件類:

       public class PersonEvent {
           private Object source;// 事件源
       
           public Object getSource() {
               return source;
           }
       
           public void setSource(Object source) {
               this.source = source;
           }
       
           // 提供一個(gè)這樣的構(gòu)造方法:構(gòu)造事件對(duì)象時(shí),接收事件源(Person)
           public PersonEvent(Person person) {
               this.source = person;
           }
       
       }
      
    4. 在事件源中注冊(cè)監(jiān)聽(tīng)器

       public class Person {
           private String name;
           private int weight;// 體重
           private PersonListener listener;
       
           // 注冊(cè)監(jiān)聽(tīng)器
           public void addPersonListener(PersonListener listener) {
               this.listener = listener;
           }
           public String getName() {
               return name;
           }
       
           public void setName(String name) {
               this.name = name;
           }
       
           public int getWeight() {
               return weight;
           }
       
           public void setWeight(int weight) {
               this.weight = weight;
           }
       }
      
    5. 操作事件源----- 在事件源方法中婿崭,構(gòu)造事件對(duì)象拨拓,參數(shù)為當(dāng)前事件源(this),傳遞事件對(duì)象給監(jiān)聽(tīng)器的監(jiān)聽(tīng)方法:

      public class Person {
           private String name;
           private int weight;// 體重
           private PersonListener listener;
       
           // 注冊(cè)監(jiān)聽(tīng)器
           public void addPersonListener(PersonListener listener) {
               this.listener = listener;
           }
       
           // 吃飯
           public void eat() {
               // 體重增加
               weight += 5;
               // 調(diào)用監(jiān)聽(tīng)器監(jiān)聽(tīng)方法
               if (listener != null) {
                   // 監(jiān)聽(tīng)器存在
                   // 創(chuàng)建事件對(duì)象 --- 通過(guò)事件對(duì)象可以獲得事件源
                   PersonEvent event = new PersonEvent(this);
       
                   listener.personeating(event);
               }
           }
           public String getName() {
               return name;
           }
       
           public void setName(String name) {
               this.name = name;
           }
       
           public int getWeight() {
               return weight;
           }
       
           public void setWeight(int weight) {
               this.weight = weight;
           }
       }
      
    6. 測(cè)試

      public class PersonTest {
           public static void main(String[] args) {
               // 步驟一 創(chuàng)建事件源
               Person person = new Person();
               person.setName("小明");
               person.setWeight(100);
       
               // 步驟二 給事件源注冊(cè)監(jiān)聽(tīng)器(該監(jiān)聽(tīng)器由匿名內(nèi)部類創(chuàng)建)
               person.addPersonListener(new PersonListener() {
                   @Override
                   public void personeating(PersonEvent event) {
                       System.out.println("監(jiān)聽(tīng)到了氓栈,人正在吃飯渣磷!");
                       
                       // 在監(jiān)聽(tīng)方法中可以獲得事件源對(duì)象,進(jìn)而可以操作事件源對(duì)象
                       Person person = (Person) event.getSource();
                       System.out.println(person.getName());
                       System.out.println(person.getWeight());
                   }
               });
       
               // 步驟三 操作事件源
               person.eat();// 結(jié)果監(jiān)聽(tīng)方法被調(diào)用
           }
       }
      

      2授瘦、Servlet監(jiān)聽(tīng)器

      • 在Servlet規(guī)范中定義了多種類型的監(jiān)聽(tīng)器醋界,它們用于監(jiān)聽(tīng)的事件源是三個(gè)域?qū)ο缶顾危謩e為:

        • ServletContext
        • HttpSession
        • ServletRequest
      • Servlet規(guī)范針對(duì)這三個(gè)域?qū)ο笊系牟僮鳎职堰@多種類型的監(jiān)聽(tīng)器劃分為三種類型:

        • 監(jiān)聽(tīng)三個(gè)域?qū)ο蟮膭?chuàng)建和銷毀的事件監(jiān)聽(tīng)器
        • 監(jiān)聽(tīng)三個(gè)域?qū)ο蟮膶傩?Attribute)的增加和刪除的事件監(jiān)聽(tīng)器
        • 監(jiān)聽(tīng)綁定到 HttpSession 域中的某個(gè)對(duì)象的狀態(tài)的事件監(jiān)聽(tīng)器形纺。(查看API文檔)
      • 編寫 Servlet 監(jiān)聽(tīng)器:

        • 和編寫其它事件監(jiān)聽(tīng)器一樣丘侠,編寫Servlet監(jiān)聽(tīng)器也需要實(shí)現(xiàn)一個(gè)特定的接口,并針對(duì)相應(yīng)動(dòng)作覆蓋接口中的相應(yīng)方法逐样。
        • 和其它事件監(jiān)聽(tīng)器略有不同的是蜗字,Servlet監(jiān)聽(tīng)器的注冊(cè)不是直接注冊(cè)在事件源上,而是由WEB容器負(fù)責(zé)注冊(cè)脂新,開(kāi)發(fā)人員只需在web.xml文件中使用<listener>標(biāo)簽配置好監(jiān)聽(tīng)器挪捕,web容器就會(huì)自動(dòng)把監(jiān)聽(tīng)器注冊(cè)到事件源中。
        • 一個(gè) web.xml 文件中可以配置多個(gè) Servlet 事件監(jiān)聽(tīng)器戏羽,web 服務(wù)器按照它們?cè)?web.xml 文件中的注冊(cè)順序來(lái)加載和注冊(cè)這些 Serlvet 事件監(jiān)聽(tīng)器担神。配置代碼如下所示:
        <!-- 對(duì)監(jiān)聽(tīng)器進(jìn)行注冊(cè) -->
          <!-- 監(jiān)聽(tīng)器和Servlet、Filter不同始花,不需要url配置妄讯,監(jiān)聽(tīng)器執(zhí)行不是由用戶訪問(wèn)的,監(jiān)聽(tīng)器 是由事件源自動(dòng)調(diào)用的 -->
          <listener>
              <listener-class>cn.itcast.servlet.listener.MyServletContextListener</listener-class>
          </listener>
        

        3酷宵、監(jiān)聽(tīng)三個(gè)域?qū)ο髣?chuàng)建和銷毀的事件監(jiān)聽(tīng)器

        3.1亥贸、ServletContextListener

        • ServletContextListener 接口用于監(jiān)聽(tīng) ServletContext 對(duì)象的創(chuàng)建和銷毀事件。

          • 當(dāng) ServletContext 對(duì)象被創(chuàng)建時(shí)浇垦,調(diào)用接口中的方法:

              ServletContextListener.contextInitialized (ServletContextEvent sce)
            
          • 當(dāng) ServletContext 對(duì)象被銷毀時(shí)炕置,調(diào)用接口中的方法:

              ServletContextListener.contextDestroyed(ServletContextEvent sce)
            
        • ServletContext域?qū)ο蠛螘r(shí)創(chuàng)建和銷毀:

          • 創(chuàng)建:服務(wù)器啟動(dòng)時(shí),針對(duì)每一個(gè)web應(yīng)用創(chuàng)建Servletcontext
          • 銷毀:服務(wù)器關(guān)閉前男韧,先關(guān)閉代表每一個(gè)web應(yīng)用的ServletContext
        • ServletContext主要用來(lái)干什么朴摊?

          1. 保存全局應(yīng)用數(shù)據(jù)對(duì)象

            • 在服務(wù)器啟動(dòng)時(shí),對(duì)一些對(duì)象進(jìn)行初始化此虑,并且將對(duì)象保存ServletContext數(shù)據(jù)范圍內(nèi) —— 實(shí)現(xiàn)全局?jǐn)?shù)據(jù)
            • 例如:創(chuàng)建數(shù)據(jù)庫(kù)連接池
          2. 加載框架配置文件

            • Spring框架(配置文件隨服務(wù)器啟動(dòng)加載) org.springframework.web.context.ContextLoaderListener
          3. 實(shí)現(xiàn)任務(wù)調(diào)度(定時(shí)器)甚纲,啟動(dòng)定時(shí)程序

            • java.util.Timer:一種線程設(shè)施,用于安排以后在后臺(tái)線程中執(zhí)行的任務(wù)朦前,可安排任務(wù)執(zhí)行一次介杆,或者定期重復(fù)執(zhí)行。

            • Timer提供了啟動(dòng)定時(shí)任務(wù)方法 Timer.schedule()韭寸,其中有兩種方法需要記状荷凇:

              1. 在指定的一個(gè)時(shí)間時(shí)啟動(dòng)定時(shí)器,定期執(zhí)行一次

                  Timer.schedule(TimerTask task, Date firstTime, long period)  
                
              2. 在當(dāng)前時(shí)間延遲多少毫秒后啟動(dòng)定時(shí)器恩伺,定期執(zhí)行一次

                  Timer.schedule(TimerTask task, long delay, long period)  
                
            • 停止定時(shí)器赴背,取消任務(wù)

                Timer.cancel() 
              
      • demo:

        package cn.itcast.servlet.listener;
          import java.text.DateFormat;
          import java.text.ParseException;
          import java.text.SimpleDateFormat;
          import java.util.Date;
          import java.util.Timer;
          import java.util.TimerTask;
          
          import javax.servlet.ServletContext;
          import javax.servlet.ServletContextEvent;
          import javax.servlet.ServletContextListener;
          
          /**
           * 自定義 Context監(jiān)聽(tīng)器
           * 
           * @author seawind
           * 
           */
          public class MyServletContextListener implements ServletContextListener {
          
              @Override
              public void contextDestroyed(ServletContextEvent sce) {
                  System.out.println("監(jiān)聽(tīng)ServletContext對(duì)象銷毀了...");
              }
          
              @Override
              public void contextInitialized(ServletContextEvent sce) {
                  System.out.println("監(jiān)聽(tīng)ServletContext對(duì)象創(chuàng)建了...");
                  // 獲得事件源
                  ServletContext servletContext = sce.getServletContext();
                  // 向ServletContext 中保存數(shù)據(jù)
          
                  // 啟動(dòng)定時(shí)器
                  final Timer timer = new Timer();
                  // 啟動(dòng)定時(shí)任務(wù)
          
                  // timer.schedule(new TimerTask() {
                  // @Override
                  // // 這就是一個(gè)線程
                  // public void run() {
                  // System.out.println("定時(shí)器執(zhí)行了...");
                  // }
                  // }, 0, 3000); // 馬上啟動(dòng) 每隔3秒重復(fù)執(zhí)行
          
                  // 指定時(shí)間啟動(dòng)定時(shí)器
                  DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                  try {
                      Date first = dateFormat.parse("2012-08-07 10:42:00");
                      timer.schedule(new TimerTask() {
                          int i;
          
                          @Override
                          public void run() {
                              i++;
                              System.out.println("從10點(diǎn)40分開(kāi)始啟動(dòng)程序,每隔3秒重復(fù)執(zhí)行");
                              if (i == 10) {
                                  timer.cancel();// 取消定時(shí)器任務(wù)
                              }
                          }
                      }, first, 3000);
                  } catch (ParseException e) {
                      e.printStackTrace();
                  }
              }
          
          }
        

        3.2、HttpSessionListener

        • HttpSessionListener接口用于監(jiān)聽(tīng)HttpSession的創(chuàng)建和銷毀

          • 創(chuàng)建一個(gè)Session時(shí)癞尚,接口中的該方法將會(huì)被調(diào)用:

              HttpSessionListener.sessionCreated(HttpSessionEvent se) 
            
          • 銷毀一個(gè)Session時(shí)耸三,接口中的該方法將會(huì)被調(diào)用:

              HttpSessionListener.sessionDestroyed (HttpSessionEvent se) 
            
        • Session域?qū)ο髣?chuàng)建和銷毀:

          • 創(chuàng)建:瀏覽器訪問(wèn)服務(wù)器時(shí)乱陡,服務(wù)器為每個(gè)瀏覽器創(chuàng)建不同的 session 對(duì)象浇揩,服務(wù)器創(chuàng)建session
          • 銷毀:如果用戶的session的30分鐘沒(méi)有使用,session就會(huì)過(guò)期憨颠,我們?cè)赥omcat的web.xml里面也可以配置session過(guò)期時(shí)間胳徽。
        • demo:

            package cn.itcast.servlet.listener;
            
            import javax.servlet.http.HttpSession;
            import javax.servlet.http.HttpSessionEvent;
            import javax.servlet.http.HttpSessionListener;
            
            public class MyHttpSessionListener implements HttpSessionListener {
            
                @Override
                public void sessionCreated(HttpSessionEvent se) {
                    // 通過(guò)事件對(duì)象獲得session 的id 
                    System.out.println("session被創(chuàng)建了");
                    HttpSession session = se.getSession();
                    System.out.println("id:" + session.getId());
                }
            
                @Override
                public void sessionDestroyed(HttpSessionEvent se) {
                    System.out.println("session被銷毀了");
                    HttpSession session = se.getSession();
                    System.out.println("id:" + session.getId());
                }
            
            }
          

        關(guān)于HttpSession的生命周期、具體描述詳見(jiàn):JSP 會(huì)話管理

        3.3爽彤、ServletRequestListener(很少用)

        • ServletRequestListener 接口用于監(jiān)聽(tīng)ServletRequest 對(duì)象的創(chuàng)建和銷毀:
          • ServletRequest對(duì)象被創(chuàng)建時(shí)养盗,監(jiān)聽(tīng)器的requestInitialized方法將會(huì)被調(diào)用。
          • ServletRequest對(duì)象被銷毀時(shí)适篙,監(jiān)聽(tīng)器的requestDestroyed方法將會(huì)被調(diào)用往核。
        • ServletRequest域?qū)ο髣?chuàng)建和銷毀的時(shí)機(jī):
          • 創(chuàng)建:用戶每一次訪問(wèn),都會(huì)創(chuàng)建一個(gè)reqeust
          • 銷毀:當(dāng)前訪問(wèn)結(jié)束嚷节,request對(duì)象就會(huì)銷毀
        • 這個(gè)監(jiān)聽(tīng)器最需要注意的:
          • 使用forward ---- request創(chuàng)建銷毀一次 (因?yàn)檗D(zhuǎn)發(fā)本質(zhì)是一次請(qǐng)求)
          • 使用sendRedirect ---- request創(chuàng)建銷毀兩次 (因?yàn)橹囟ㄏ虮举|(zhì)是兩次請(qǐng)求)

        關(guān)于ServletRequest詳見(jiàn):http://www.reibang.com/p/7e2e3fd58e91

    springboot 配置監(jiān)聽(tīng)器:
    1.添加@WebListener注解
    @WebListener
    public class MyHttpSessionListener implements HttpSessionListener {
    2.添加@ComponentScan,@ServletComponentScan
    @ComponentScan("com.springboot.demo.*")
    @ServletComponentScan(basePackages = "com.springboot.demo.*")
    public class DemoApplication {
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末聂儒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子硫痰,更是在濱河造成了極大的恐慌衩婚,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件效斑,死亡現(xiàn)場(chǎng)離奇詭異非春,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)缓屠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門奇昙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人敌完,你說(shuō)我怎么就攤上這事储耐。” “怎么了蠢挡?”我有些...
    開(kāi)封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵弧岳,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我业踏,道長(zhǎng)禽炬,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任勤家,我火速辦了婚禮腹尖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伐脖。我一直安慰自己热幔,他們只是感情好乐设,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著绎巨,像睡著了一般近尚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上场勤,一...
    開(kāi)封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天戈锻,我揣著相機(jī)與錄音,去河邊找鬼和媳。 笑死格遭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的留瞳。 我是一名探鬼主播拒迅,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼她倘!你這毒婦竟也來(lái)了璧微?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤帝牡,失蹤者是張志新(化名)和其女友劉穎往毡,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體靶溜,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡开瞭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了罩息。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗤详。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖瓷炮,靈堂內(nèi)的尸體忽然破棺而出葱色,到底是詐尸還是另有隱情,我是刑警寧澤娘香,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布苍狰,位于F島的核電站,受9級(jí)特大地震影響烘绽,放射性物質(zhì)發(fā)生泄漏淋昭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一安接、第九天 我趴在偏房一處隱蔽的房頂上張望翔忽。 院中可真熱鬧,春花似錦、人聲如沸歇式。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)材失。三九已至痕鳍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間豺憔,已是汗流浹背额获。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恭应,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓耘眨,卻偏偏與公主長(zhǎng)得像昼榛,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子剔难,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 本文包括:1胆屿、Listener簡(jiǎn)介2、Servlet監(jiān)聽(tīng)器3偶宫、監(jiān)聽(tīng)三個(gè)域?qū)ο髣?chuàng)建和銷毀的事件監(jiān)聽(tīng)器4非迹、監(jiān)聽(tīng)三個(gè)域?qū)?..
    廖少少閱讀 6,067評(píng)論 6 28
  • 監(jiān)聽(tīng)器(listener) 監(jiān)聽(tīng)器簡(jiǎn)介 :監(jiān)聽(tīng)器就是一個(gè)實(shí)現(xiàn)特定接口的普通java程序,這個(gè)程序?qū)iT用于監(jiān)聽(tīng)另一個(gè)...
    奮斗的老王閱讀 2,507評(píng)論 0 53
  • 1纯趋、過(guò)濾器的基本概念 現(xiàn)實(shí)中的監(jiān)聽(tīng)器定義:是指專門用于對(duì)其他對(duì)象身上發(fā)生的事件或狀態(tài)改變進(jìn)行監(jiān)聽(tīng)和相應(yīng)處理的對(duì)象憎兽,...
    年少懵懂丶流年夢(mèng)閱讀 332評(píng)論 1 2
  • 僅作為自己學(xué)習(xí)記錄使用,文章來(lái)自: 1吵冒、http://blog.csdn.net/csh624366188/art...
    BakerZhang閱讀 1,013評(píng)論 1 5
  • 一痹栖、概述 監(jiān)聽(tīng)器就是一個(gè)實(shí)現(xiàn)特定接口的普通java程序亿汞,這個(gè)程序?qū)iT用于監(jiān)聽(tīng)另一個(gè)java對(duì)象的方法調(diào)用或?qū)傩愿淖?..
    yjaal閱讀 1,995評(píng)論 0 5