最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解JavaWeb中的 Listener

 更新時間:2016年09月28日 16:21:59   作者:南唐三少  
JavaWeb里面的listener是通過觀察者設計模式進行實現(xiàn)的。下面通過本文給大家詳細介紹javaweb中的listener,感興趣的朋友一起看看吧

一、基本概念

JavaWeb里面的listener是通過觀察者設計模式進行實現(xiàn)的。對于觀察者模式,這里不做過多介紹,大概講一下什么意思。

觀察者模式又叫發(fā)布訂閱模式或者監(jiān)聽器模式。在該模式中有兩個角色:觀察者和被觀察者(通常也叫做主題)。觀察者在主題里面注冊自己感興趣的事件,當這個事件發(fā)生時,主題會通過回調(diào)接口的方式通知觀察者。

舉個生活中的例子:訂閱報紙。任何一個家庭或個人都可以向報社訂閱報紙。這里報社就是“主題”,家庭就是“觀察者”。比如家庭需要訂閱明天早晨的報紙,這個就是“事件”。到了第二天早晨,報紙生產(chǎn)出來了,這個就是“事件發(fā)生”。當事件發(fā)生時,送報員將報紙送到家庭的信箱里面,這里的信箱就是“回調(diào)接口”。

對于JavaWeb里面的監(jiān)聽器,Servlet規(guī)范定義了一些列的Listener接口類,通過接口類的方式將事件暴露給應用程序,應用程序如果想監(jiān)聽其感興趣的事件,那么不必去直接注冊對應的事件,而是編寫自己的listener實現(xiàn)相應的接口類,并將自己的listener注冊到servlet容器。當程序關心的事件發(fā)生時,servlet容器會通知listener,回調(diào)listener里面的方法。這里自定義的listener就是觀察者,servlet容器就是主題。

二、樣例分析

上面說了,servlet容器是通過Listener接口類將事件暴露給應用程序的。所以我們與其說是注冊事件,不如說是注冊監(jiān)聽器。對應到編程步驟就是:1.編寫自己的listener,實現(xiàn)特定的Listener接口。2.在web.xml里面注冊自己的listener。這里以最簡單的監(jiān)聽器接口ServletContextListener舉例:

1.TestListener.java

public class TestListener implements ServletContextListener {
public TestListener() {}
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContextListener.contextInitialized");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContextListener.contextDestroyed");
}
}

2.web.xml

<listener>
<listener-class>com.nantang.listener.TestListener</listener-class>
</listener>

當容器啟動時會向日志中輸出"ServletContextListener.contextInitialized",當容器關閉時會輸出"ServletContextListener.contextDestroyed"。詳細的解釋后面會進一步分析。

這里需要注意是,如果在IDE(Eclipse、STS等)演示上面的例子,當啟動服務器時,在控制臺可以看到"ServletContextListener.contextInitialized",當關閉服務器時,是看不到"ServletContextListener.contextDestroyed"的。這不是沒有執(zhí)行contextDestroyed方法,而是IDE實現(xiàn)的不夠完美。要想驗證確實調(diào)用了contextDestroyed,可以在contextDestroyed里面寫一段代碼邏輯往文件輸出內(nèi)容而不要輸出到控制臺。

三、源碼分析

現(xiàn)在我們分析下,servlet規(guī)范為我們定義了哪些事件。更準確的說是定義了哪些監(jiān)聽接口。下面的介紹都是以servlet3.0規(guī)范為準。

servlet3.0為我們提供了8個監(jiān)聽器接口,按照它們的作用域來劃分的話可以分為三類:

1.servlet上下文相關監(jiān)聽接口,包括:ServletContextListener和ServletContextAttributeListener。

2.http session相關監(jiān)聽接口,包括:HttpSessionListener、HttpSessionActivationListener、HttpSessionAttributeListener和HttpSessionBindingListener。

3.servlet request相關監(jiān)聽接口,包括:ServletRequestListener和ServletRequestAttributeListener。

其實從接口的命名,各位看官應該能猜出其基本功能。下面我們按分類來解釋。

1.servlet上下文相關監(jiān)聽接口

之前在介紹Servlet的時候,我們解釋過一個web應用對應一個servlet上下文。所以ServletContextListener和ServletContextAttributeListener監(jiān)聽的事件的生命范圍是貫穿整個web應用的。下面是這兩個接口的類圖層級關系。

 

1.1 EventListener

EventListener是一個標記接口,所有的事件監(jiān)聽器都必須繼承這個接口,這就是servlet規(guī)范,沒什么好解釋的。

1.2 EventObject

和EventListener類似,EventObject是個事件頂級類,所有具體的事件類都必須繼承EventObject。

public class EventObject implements java.io.Serializable {
protected transient Object source;
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
public Object getSource() {
return source;
}
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}

這個類很簡單,其本質就一個東西:source。通過類名EventObject和屬性名source,就能看出這個類就干了一件事,持有“事件源對象”。

1.3 ServletContextEvent

public class ServletContextEvent extends java.util.EventObject { 
public ServletContextEvent(ServletContext source) {
super(source);
}
public ServletContext getServletContext () { 
return (ServletContext) super.getSource();
}
}

servlet上下文事件,這個事件類就是對EventObject的簡單繼承。構造方法中提供ServletContext實例作為事件源。因為事件源是servlet上下文,所以提供個getServletContext獲取ServletContext實例。

在我們后續(xù)講解其他事件類的時候,都是一個模子,每個事件類都提供相應的構造方法,傳入相應的事件源對象,并提供額外的獲取事件源方法。所以EventObject就是個事件源的基類,所有事件子類的本質就干了一件事,確定具體的事件源對象。

所以我們后面講解事件的地方,一帶而過。

1.4 ServletContextListener

public interface ServletContextListener extends EventListener {
public void contextInitialized ( ServletContextEvent sce );
public void contextDestroyed ( ServletContextEvent sce );
}

servlet上下文監(jiān)聽器接口,對應著兩個事件:servlet上下文初始化事件和servlet上下文即將關閉事件。

當web應用初始化的時候,servlet容器會構造ServletContextEven實例,并回調(diào)contextInitialize方法。

當servlet上下文即將關閉時,一般是關閉服務器之前,servlet容器會構造ServletContextEven實例,并回調(diào)contextDestroyed方法。這里需要注意的是,contextDestroyed方法的執(zhí)行會在所有的servlet和filter執(zhí)行完destroy方法之后。

所以如果我們想在應用啟動或關閉時需要做些事情的話,就編寫自己的listener實現(xiàn)該接口。

所有的事件監(jiān)聽器也是一個模子,按照servlet規(guī)范定義相應的事件回調(diào)接口方法,方法的入?yún)⒕褪窍鄳氖录磳嵗?。所以我們后面講解監(jiān)聽器的地方也一帶而過。

1.5 ServletContextAttributeEvent

public class ServletContextAttributeEvent extends ServletContextEvent { 
private String name;
private Object value;
public ServletContextAttributeEvent(ServletContext source, String name, Object value) {
super(source);
this.name = name;
this.value = value;
}
public String getName() {
return this.name;
}
public Object getValue() {
return this.value; 
}
}

ServletContextAttributeEvent表示servlet上下文屬性相關事件,一般當屬性發(fā)生改變時會觸發(fā)該事件。這個類繼承ServletContextEven,事件源也是ServletContext實例。額外提供屬性名和屬性值的獲取方法。

1.6 ServletContextAttributeListener

public interface ServletContextAttributeListener extends EventListener {
public void attributeAdded(ServletContextAttributeEvent scab);
public void attributeRemoved(ServletContextAttributeEvent scab);
public void attributeReplaced(ServletContextAttributeEvent scab);
}

當servlet上文屬性發(fā)生增、刪、改的時候,servlet容器構造ServletContextAttributeEvent事件對象,分別回調(diào)attributeAdded、attributeRemoved、attributeReplaced方法。

這里需要注意的是attributeReplaced方法,當屬性的值被替換的時候回調(diào)。這個時候如果調(diào)用ServletContextAttributeEvent.getValue()方法返回的是替換之前的屬性值。

2 http session相關監(jiān)聽接口

2.1 HttpSessionEvent

public class HttpSessionEvent extends java.util.EventObject {
public HttpSessionEvent(HttpSession source) {
super(source);
}
public HttpSession getSession () { 
return (HttpSession) super.getSource();
}
}

http session相關事件,當session發(fā)生變化時會觸發(fā)該事件。事件源是HttpSession實例,并提供額外的HttpSession獲取方法。

2.2 HttpSessionListener

public interface HttpSessionListener extends EventListener {
public void sessionCreated ( HttpSessionEvent se );
public void sessionDestroyed ( HttpSessionEvent se );
}

當session被創(chuàng)建和銷毀的時候,servlet容器構造HttpSessionEvent事件對象,并回調(diào)sessionCreated和sessionDestroyed方法。

2.3 HttpSessionActivationListener

public interface HttpSessionActivationListener extends EventListener { 
public void sessionWillPassivate(HttpSessionEvent se); 
public void sessionDidActivate(HttpSessionEvent se);
}

當session將要鈍化或已被激活時,servlet容器構造HttpSessionEvent事件對象,回調(diào)sessionWillPassivate和sessionDidActivate方法。

這里解釋下鈍化和激活:鈍化是指服務器內(nèi)存不夠了或者session的活動超時時間到了,把最近不活動的session序列化到磁盤。激活是指某個鈍化的session又被訪問了,從磁盤將session反序列化到內(nèi)存。

這里可以看出要想鈍化和激活,首先session得可序列化和反序列化。同時我們在編程過程中,session盡量用String、Integer等簡單的對象,盡量不要用list、map等集合。

2.4 HttpSessionBindingEvent

public class HttpSessionBindingEvent extends HttpSessionEvent {
private String name;
private Object value;
public HttpSessionBindingEvent(HttpSession session, String name) {
super(session);
this.name = name;
}
public HttpSessionBindingEvent(HttpSession session, String name, Object value) {
super(session);
this.name = name;
this.value = value;
}
public HttpSession getSession () { 
return super.getSession();
}
public String getName() {
return name;
}
public Object getValue() {
return this.value; 
}
}

http session的屬性相關事件,當session屬性發(fā)生變化時會觸發(fā)該事件。事件源是HttpSession實例,并提供額外的獲取HttpSession、屬性名、屬性值的方法。

2.5 HttpSessionAttributeListener

public interface HttpSessionAttributeListener extends EventListener {
public void attributeAdded ( HttpSessionBindingEvent se );
public void attributeRemoved ( HttpSessionBindingEvent se );
public void attributeReplaced ( HttpSessionBindingEvent se );
}

當session屬性發(fā)生增、刪、改的時候,servlet容器構造HttpSessionBindingEvent事件對象,分別回調(diào)attributeAdded、attributeRemoved、attributeReplaced方法。

這里需要注意的是attributeReplaced方法,當屬性的值被替換的時候回調(diào)。這個時候如果調(diào)用ServletContextAttributeEvent.getValue()方法返回的是替換之前的屬性值。

當調(diào)用session的invalidate方法或者session失效時,也會回調(diào)attributeRemoved方法。

2.6 HttpSessionBindingListener

public interface HttpSessionBindingListener extends EventListener {
public void valueBound(HttpSessionBindingEvent event);
public void valueUnbound(HttpSessionBindingEvent event);
}

這個監(jiān)聽器也是監(jiān)聽session的屬性變化。當session屬性發(fā)生增和刪,也就是屬性值綁定和屬性值解綁的時候,servlet容器構造HttpSessionBindingEvent事件對象,分別回調(diào)valueBound、valueUnbound方法。

這么一看和HttpSessionAttributeListener沒什么區(qū)別,其實不是這樣。兩者有個本質的區(qū)別就是事件觸發(fā)的條件。

當session的屬性有任何的變化,servlet容器都會通知HttpSessionAttributeListener。但是對于HttpSessionBindingListener,只有當綁定或解綁的屬性值是監(jiān)聽器的實例時,servlet容器才會通知。舉例來說:

public class TestListener implements HttpSessionBindingListener{
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("HttpSessionBindingListener.valueBound");
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("HttpSessionBindingListener.valueUnbound");
}
}

我們自定義監(jiān)聽器TestListener實現(xiàn)HttpSessionBindingListener,下面我們在代碼中設置如下session屬性:

HttpSession session = request.getSession();
TestListener testListener=new TestListener();
session.setAttribute("listener", testListener);
session.removeAttribute("listener");

這里session的屬性值是我們的監(jiān)聽器TestListener實例。所以這段代碼執(zhí)行時,servlet容器會通知TestListener并回調(diào)valueBound和valueUnbound方法。

這里需要注意的是,當調(diào)用session的invalidate方法或者session失效時,也會回調(diào)valueUnbound方法。

3 servlet request相關監(jiān)聽接口

3.1 ServletRequestEvent

public class ServletRequestEvent extends java.util.EventObject { 
private ServletRequest request;
public ServletRequestEvent(ServletContext sc, ServletRequest request) {
super(sc);
this.request = request;
}
public ServletRequest getServletRequest () { 
return this.request;
}
public ServletContext getServletContext () { 
return (ServletContext) super.getSource();
}
}

servlet請求的相關事件,當request發(fā)生變化時會觸發(fā)該事件。事件源是ServletContext實例,并提供額外的獲取ServletContext和ServletRequest方法。

3.2 ServletRequestListener

public interface ServletRequestListener extends EventListener {
public void requestDestroyed ( ServletRequestEvent sre );
public void requestInitialized ( ServletRequestEvent sre );
}

當請求初始化或者銷毀時,即客戶端請求進入web應用(進入servlet或者第一個filter)或web應用返回響應給客戶端(退出servlet或者第一個filter)。servlet容器構造ServletRequestEvent實例,回調(diào)requestInitialized和requestDestroyed方法。

3.3 ServletRequestAttributeEvent

public class ServletRequestAttributeEvent extends ServletRequestEvent { 
private String name;
private Object value;
public ServletRequestAttributeEvent(ServletContext sc, ServletRequest request, String name, Object value) {
super(sc, request);
this.name = name;
this.value = value;
}
public String getName() {
return this.name;
}
public Object getValue() {
return this.value; 
}
}

servlet請求屬性的相關事件,當請求屬性發(fā)生變化時會觸發(fā)該事件。事件源是ServletContext實例,并提供額外的獲取屬性名和屬性值的方法。

3.4 ServletRequestAttributeListener

public interface ServletRequestAttributeListener extends EventListener {
public void attributeAdded(ServletRequestAttributeEvent srae);
public void attributeRemoved(ServletRequestAttributeEvent srae);
public void attributeReplaced(ServletRequestAttributeEvent srae);
}

當請求的屬性發(fā)生增、刪、改的時候,servlet容器構造ServletRequestAttributeEvent事件對象,分別回調(diào)attributeAdded、attributeRemoved、attributeReplaced方法。

這里需要注意的是attributeReplaced方法,當屬性的值被替換的時候回調(diào)。這個時候如果調(diào)用ServletRequestAttributeEvent.getValue()方法返回的是替換之前的屬性值。

四、總結

至此,listener講完了。我們可以發(fā)現(xiàn)listener和servlet、filter有個共同點,都是由容器進行調(diào)度。我們只需要編寫自己的listener去實現(xiàn)我們關心的監(jiān)聽器接口并注冊,剩下來的工作就是在我們自己的listener里面編寫業(yè)務邏輯。

這邊博文介紹的listener是servlet3.0規(guī)范制定的。3.1已經(jīng)增加了一些事件監(jiān)聽器接口,道理都是類似的,讀者可以自行去了解。

相關文章

  • tio-boot框架整合ehcache實現(xiàn)過程示例

    tio-boot框架整合ehcache實現(xiàn)過程示例

    這篇文章主要為大家介紹了tio-boot框架整合ehcache實現(xiàn)過程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • Mybatis-Plus中update()和updateById()將字段更新為null

    Mybatis-Plus中update()和updateById()將字段更新為null

    本文主要介紹了Mybatis-Plus中update()和updateById()將字段更新為null,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • 使用注解+RequestBodyAdvice實現(xiàn)http請求內(nèi)容加解密方式

    使用注解+RequestBodyAdvice實現(xiàn)http請求內(nèi)容加解密方式

    這篇文章主要介紹了使用注解+RequestBodyAdvice實現(xiàn)http請求內(nèi)容加解密方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java面試官最喜歡問的關鍵字之volatile詳解

    Java面試官最喜歡問的關鍵字之volatile詳解

    這篇文章主要給大家介紹了關于Java面試官最喜歡問的關鍵字之volatile的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-03-03
  • SpringBoot集成MaxCompute的示例代碼

    SpringBoot集成MaxCompute的示例代碼

    這篇文章主要介紹了SpringBoot集成MaxCompute的實例代碼,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • 利用Java+MySQL實現(xiàn)附近功能實例

    利用Java+MySQL實現(xiàn)附近功能實例

    現(xiàn)在很多手機軟件都用附近搜索功能,但具體是怎么實現(xiàn)的呢?下面這篇文章就來給大家介紹關于利用Java+MySQL實現(xiàn)附近功能的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-12-12
  • Spring-retry實現(xiàn)循環(huán)重試功能

    Spring-retry實現(xiàn)循環(huán)重試功能

    這篇文章主要介紹了Spring-retry 優(yōu)雅的實現(xiàn)循環(huán)重試功能,通過@Retryable注解,優(yōu)雅的實現(xiàn)循環(huán)重試功能,需要的朋友可以參考下
    2023-07-07
  • JavaWeb請求轉發(fā)和請求包含實現(xiàn)過程解析

    JavaWeb請求轉發(fā)和請求包含實現(xiàn)過程解析

    這篇文章主要介紹了JavaWeb請求轉發(fā)和請求包含實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-02-02
  • SpringBoot快速接入OpenAI大模型的方法(JDK8)

    SpringBoot快速接入OpenAI大模型的方法(JDK8)

    本文介紹了如何使用AI4J快速接入OpenAI大模型,并展示了如何實現(xiàn)流式與非流式的輸出,以及對函數(shù)調(diào)用的使用,AI4J支持JDK8,適用于多種應用場景,包括Spring Boot項目,感興趣的朋友一起看看吧
    2025-02-02
  • SpringBoot超詳細講解事務管理

    SpringBoot超詳細講解事務管理

    事務的作用就是為了保證用戶的每一個操作都是可靠的,事務中的每一步操作都必須成功執(zhí)行,只要有發(fā)生異常就 回退到事務開始未進行操作的狀態(tài)。事務管理是Spring框架中最為常用的功能之一,我們在使用Spring Boot開發(fā)應用時,大部分情況下也都需要使用事務
    2022-08-08

最新評論

七台河市| 浦东新区| 偃师市| 安塞县| 白银市| 石门县| 花垣县| 上蔡县| 会同县| 湘潭市| 巢湖市| 湖口县| 宁阳县| 贵溪市| 阿瓦提县| 裕民县| 漳平市| 太仆寺旗| 潼南县| 沙田区| 合山市| 洞口县| 扎鲁特旗| 札达县| 泰顺县| 来宾市| 乌海市| 江永县| 盐源县| 高碑店市| 丰原市| 连平县| 昭觉县| 鄂尔多斯市| 旬阳县| 恭城| 四子王旗| 临猗县| 临泽县| 永顺县| 社旗县|