摘要:但監(jiān)聽器要在事件源上實(shí)現(xiàn)接口也就是說,直接用一個(gè)類實(shí)現(xiàn)和接口是監(jiān)聽不到內(nèi)對(duì)象的變化的。
什么是監(jiān)聽器
監(jiān)聽器就是一個(gè)實(shí)現(xiàn)特定接口的普通java程序,這個(gè)程序?qū)iT用于監(jiān)聽另一個(gè)java對(duì)象的方法調(diào)用或?qū)傩愿淖?/strong>,當(dāng)被監(jiān)聽對(duì)象發(fā)生上述事件后,監(jiān)聽器某個(gè)方法將立即被執(zhí)行。。為什么我們要使用監(jiān)聽器?
監(jiān)聽器可以用來檢測(cè)網(wǎng)站的在線人數(shù),統(tǒng)計(jì)網(wǎng)站的訪問量等等!
監(jiān)聽器組件監(jiān)聽器涉及三個(gè)組件:事件源,事件對(duì)象,事件監(jiān)聽器
當(dāng)事件源發(fā)生某個(gè)動(dòng)作的時(shí)候,它會(huì)調(diào)用事件監(jiān)聽器的方法,并在調(diào)用事件監(jiān)聽器方法的時(shí)候把事件對(duì)象傳遞進(jìn)去。
我們?cè)诒O(jiān)聽器中就可以通過事件對(duì)象獲取得到事件源,從而對(duì)事件源進(jìn)行操作!
模擬監(jiān)聽器既然上面已經(jīng)說了監(jiān)聽器的概念了,監(jiān)聽器涉及三個(gè)組件:事件源,事件對(duì)象,事件監(jiān)聽器。
我們就寫一個(gè)對(duì)象,被監(jiān)聽器監(jiān)聽
監(jiān)聽器監(jiān)聽器定義為接口,監(jiān)聽的方法需要事件對(duì)象傳遞進(jìn)來,從而在監(jiān)聽器上通過事件對(duì)象獲取得到事件源,對(duì)事件源進(jìn)行修改!
/** * 事件監(jiān)聽器 * * 監(jiān)聽Person事件源的eat和sleep方法 */ interface PersonListener{ void doEat(Event event); void doSleep(Event event); }事件源
事件源是一個(gè)Person類,它有eat和sleep()方法。
事件源需要注冊(cè)監(jiān)聽器(即在事件源上關(guān)聯(lián)監(jiān)聽器對(duì)象)
如果觸發(fā)了eat或sleep()方法的時(shí)候,會(huì)調(diào)用監(jiān)聽器的方法,并將事件對(duì)象傳遞進(jìn)去
/** * * 事件源Person * * 事件源要提供方法注冊(cè)監(jiān)聽器(即在事件源上關(guān)聯(lián)監(jiān)聽器對(duì)象) */ class Person { //在成員變量定義一個(gè)監(jiān)聽器對(duì)象 private PersonListener personListener ; //在事件源中定義兩個(gè)方法 public void Eat() { //當(dāng)事件源調(diào)用了Eat方法時(shí),應(yīng)該觸發(fā)監(jiān)聽器的方法,調(diào)用監(jiān)聽器的方法并把事件對(duì)象傳遞進(jìn)去 personListener.doEat(new Event(this)); } public void sleep() { //當(dāng)事件源調(diào)用了Eat方法時(shí),應(yīng)該觸發(fā)監(jiān)聽器的方法,調(diào)用監(jiān)聽器的方法并把事件對(duì)象傳遞進(jìn)去 personListener.doSleep(new Event(this)); } //注冊(cè)監(jiān)聽器,該類沒有監(jiān)聽器對(duì)象啊,那么就傳遞進(jìn)來吧。 public void registerLister(PersonListener personListener) { this.personListener = personListener; } }事件對(duì)象
事件對(duì)象封裝了事件源。
監(jiān)聽器可以從事件對(duì)象上獲取得到事件源的對(duì)象(信息)
/** * 事件對(duì)象Even * * 事件對(duì)象封裝了事件源 * * 在監(jiān)聽器上能夠通過事件對(duì)象獲取得到事件源 * * */ class Event{ private Person person; public Event() { } public Event(Person person) { this.person = person; } public Person getResource() { return person; } }測(cè)試
public static void main(String[] args) { Person person = new Person(); //注冊(cè)監(jiān)聽器() person.registerLister(new PersonListener() { @Override public void doEat(Event event) { Person person1 = event.getResource(); System.out.println(person1 + "正在吃飯呢!"); } @Override public void doSleep(Event event) { Person person1 = event.getResource(); System.out.println(person1 + "正在睡覺呢!"); } }); //當(dāng)調(diào)用eat方法時(shí),觸發(fā)事件,將事件對(duì)象傳遞給監(jiān)聽器,最后監(jiān)聽器獲得事件源,對(duì)事件源進(jìn)行操作 person.Eat(); }
事件源:擁有事件
監(jiān)聽器:監(jiān)聽事件源所擁有的事件(帶事件對(duì)象參數(shù)的)
事件對(duì)象:事件對(duì)象封裝了事件源對(duì)象
事件源要與監(jiān)聽器有關(guān)系,就得注冊(cè)監(jiān)聽器【提供方法得到監(jiān)聽器對(duì)象】
觸發(fā)事件源的事件,實(shí)際會(huì)提交給監(jiān)聽器對(duì)象處理,并且把事件對(duì)象傳遞過去給監(jiān)聽器。
Servle監(jiān)聽器在Servlet規(guī)范中定義了多種類型的監(jiān)聽器,它們用于監(jiān)聽的事件源分別 ServletContext, HttpSession和ServletRequest這三個(gè)域?qū)ο?/strong>
和其它事件監(jiān)聽器略有不同的是,servlet監(jiān)聽器的注冊(cè)不是直接注冊(cè)在事件源上,而是由WEB容器負(fù)責(zé)注冊(cè),開發(fā)人員只需在web.xml文件中使用
HttpSessionListener、ServletContextListener、ServletRequestListener分別監(jiān)控著Session、Context、Request對(duì)象的創(chuàng)建和銷毀
HttpSessionListener(可以用來收集在線者信息)
ServletContextListener(可以獲取web.xml里面的參數(shù)配置)
ServletRequestListener
測(cè)試public class Listener1 implements ServletContextListener, HttpSessionListener, ServletRequestListener { // Public constructor is required by servlet spec public Listener1() { } public void contextInitialized(ServletContextEvent sce) { System.out.println("容器創(chuàng)建了"); } public void contextDestroyed(ServletContextEvent sce) { System.out.println("容器銷毀了"); } public void sessionCreated(HttpSessionEvent se) { System.out.println("Session創(chuàng)建了"); } public void sessionDestroyed(HttpSessionEvent se) { System.out.println("Session銷毀了"); } @Override public void requestDestroyed(ServletRequestEvent servletRequestEvent) { } @Override public void requestInitialized(ServletRequestEvent servletRequestEvent) { } }
監(jiān)聽器監(jiān)聽到ServletContext的初始化了,Session的創(chuàng)建和ServletContext的銷毀。(服務(wù)器停掉,不代表Session就被銷毀了。Session的創(chuàng)建是在內(nèi)存中的,所以沒看到Session被銷毀了)
監(jiān)聽對(duì)象屬性變化ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener分別監(jiān)聽著Context、Session、Request對(duì)象屬性的變化
這三個(gè)接口中都定義了三個(gè)方法來處理被監(jiān)聽對(duì)象中的屬性的增加,刪除和替換的事件,同一個(gè)事件在這三個(gè)接口中對(duì)應(yīng)的方法名稱完全相同,只是接受的參數(shù)類型不同。
attributeAdded()
attributeRemoved()
attributeReplaced()
測(cè)試這里我只演示Context對(duì)象,其他對(duì)象都是以此類推的,就不一一測(cè)試了。
實(shí)現(xiàn)ServletContextAttributeListener接口。
public class Listener1 implements ServletContextAttributeListener { @Override public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) { System.out.println("Context對(duì)象增加了屬性"); } @Override public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) { System.out.println("Context對(duì)象刪除了屬性"); } @Override public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) { System.out.println("Context對(duì)象替換了屬性"); } }
測(cè)試的Servlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletContext context = this.getServletContext(); context.setAttribute("aa", "123"); context.setAttribute("aa", "234"); context.removeAttribute("aa"); }監(jiān)聽Session內(nèi)的對(duì)象
除了上面的6種Listener,還有兩種Linstener監(jiān)聽Session內(nèi)的對(duì)象,分別是HttpSessionBindingListener和HttpSessionActivationListener,實(shí)現(xiàn)這兩個(gè)接口并不需要在web.xml文件中注冊(cè)
實(shí)現(xiàn)HttpSessionBindingListener接口,JavaBean 對(duì)象可以感知自己被綁定到 Session 中和從 Session 中刪除的事件【和HttpSessionAttributeListener的作用是差不多的】
實(shí)現(xiàn)HttpSessionActivationListener接口,JavaBean 對(duì)象可以感知自己被活化和鈍化的事件(當(dāng)服務(wù)器關(guān)閉時(shí),會(huì)將Session的內(nèi)容保存在硬盤上【鈍化】,當(dāng)服務(wù)器開啟時(shí),會(huì)將Session的內(nèi)容在硬盤式重新加載【活化】) 。。
想要測(cè)試出Session的硬化和鈍化,需要修改Tomcat的配置的。在META-INF下的context.xml文件中添加下面的代碼:
測(cè)試
監(jiān)聽器和事件源
/* * 由于涉及到了將內(nèi)存的Session鈍化到硬盤和用硬盤活化到內(nèi)存中,所以需要實(shí)現(xiàn)Serializable接口 * * 該監(jiān)聽器是不需要在web.xml文件中配置的。但監(jiān)聽器要在事件源上實(shí)現(xiàn)接口 * 也就是說,直接用一個(gè)類實(shí)現(xiàn)HttpSessionBindingListener和HttpSessionActivationListener接口是監(jiān)聽不到Session內(nèi)對(duì)象的變化的。 * 因?yàn)樗鼈兪歉兄约涸赟ession中的變化! * */ public class User implements HttpSessionBindingListener,HttpSessionActivationListener,Serializable { private String username ; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) { HttpSession httpSession = httpSessionEvent.getSession(); System.out.println("鈍化了"); } @Override public void sessionDidActivate(HttpSessionEvent httpSessionEvent) { HttpSession httpSession = httpSessionEvent.getSession(); System.out.println("活化了"); } @Override public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) { System.out.println("綁定了對(duì)象"); } @Override public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) { System.out.println("解除了對(duì)象"); } }
測(cè)試代碼
User user = new User(); request.getSession().setAttribute("aaa", user); request.getSession().removeAttribute("aaa");
效果:
如果文章有錯(cuò)的地方歡迎指正,大家互相交流。習(xí)慣在微信看技術(shù)文章的同學(xué),可以關(guān)注微信公眾號(hào):Java3y
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/70957.html
摘要:如果遇到非常的復(fù)雜的匹配,正則表達(dá)式的優(yōu)勢(shì)就更加明顯了。關(guān)于正則表達(dá)式書寫規(guī)則,可查看,上面說的很清楚了,我就不貼出來了。替換與正則表達(dá)式匹配的子串,并返回替換后的字符串。結(jié)語正則表達(dá)式并不難,懂了其中的套路之后,一切都變得簡(jiǎn)單了。 前言 在正文開始前,先說說正則表達(dá)式是什么,為什么要用正則表達(dá)式?正則表達(dá)式在我個(gè)人看來就是一個(gè)瀏覽器可以識(shí)別的規(guī)則,有了這個(gè)規(guī)則,瀏覽器就可以幫我們判斷...
摘要:從入門到放棄是什么,黑歷史,不講,自己百度去。類你沒有看錯(cuò),這里面的就沒有問題的。之前我們用過,和有了,再也不用這兩個(gè)貨了。一個(gè)函數(shù),可以遍歷狀態(tài)感覺就是狀態(tài)機(jī),好吧不說了再說就懵逼了。 ES6從入門到放棄 1.ES6是什么,黑歷史,不講,自己百度去。 2.在瀏覽器中如何使用? 1.babel babeljs.io在線編譯 2.traceur-----Google出的編譯器,把E...
摘要:注解在類上為類提供一個(gè)全參的構(gòu)造方法,加了這個(gè)注解后,類中不提供默認(rèn)構(gòu)造方法了。這個(gè)注解用在類上,使用類中所有帶有注解的或者帶有修飾的成員變量生成對(duì)應(yīng)的構(gòu)造方法。 轉(zhuǎn)載請(qǐng)注明原創(chuàng)地址:http://www.54tianzhisheng.cn/2018/01/07/lombok/ showImg(http://ohfk1r827.bkt.clouddn.com/blog/180107/7...
摘要:縮進(jìn)不一致,會(huì)導(dǎo)致運(yùn)行錯(cuò)誤。變量變量在使用前必須先定義即賦予變量一個(gè)值,否則會(huì)報(bào)錯(cuò)數(shù)據(jù)類型布爾只有和兩個(gè)值,表示真或假。 簡(jiǎn)介 Python 是一種高層次的結(jié)合了解釋性、編譯性、互動(dòng)性和面向?qū)ο蟮哪_本語言。Python 由 Guido van Rossum 于 1989 年底在荷蘭國家數(shù)學(xué)和計(jì)算機(jī)科學(xué)研究所發(fā)明,第一個(gè)公開發(fā)行版發(fā)行于 1991 年。 特點(diǎn) 易于學(xué)習(xí):Python ...
摘要:動(dòng)態(tài)地代理,可以猜測(cè)一下它的含義,在運(yùn)行時(shí)動(dòng)態(tài)地對(duì)某些東西代理,代理它做了其他事情。所以動(dòng)態(tài)代理的內(nèi)容重點(diǎn)就是這個(gè)。所以下一篇我們來細(xì)致了解下的到底是怎么使用動(dòng)態(tài)代理的。 之前講了《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》,本來打算下一篇講講Srping的AOP的,但是其中會(huì)涉及到Java的動(dòng)態(tài)代理,所以先單獨(dú)一篇來了解下Java的動(dòng)態(tài)代理到底是什么,Java是怎么實(shí)現(xiàn)它的。 ...
閱讀 1624·2021-11-16 11:45
閱讀 2555·2021-09-29 09:48
閱讀 3320·2021-09-07 10:26
閱讀 1848·2021-08-16 10:50
閱讀 1878·2019-08-30 15:44
閱讀 2706·2019-08-28 18:03
閱讀 1907·2019-08-27 10:54
閱讀 1832·2019-08-26 14:01