iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 10
0

前言

今天來整理一下Listener監聽器
為本書的範圍ch5


定義

因為ServletContext只能提供字串類的初始參數
無法將物件類的型態傳入DD裡面
因此Listener就是要負責偵聽Context初始化前
先去執行一個獨立的類別
去解析所要的參數,取出其內容
照本書的例子是說明使用在建立資料庫連接的部分

主要需要下列部分:

  • XXXXServletContextListener
    =>實作ServletContextListener interface
    會從DD裡取出初始參數,並呼叫目標類別,設定在新的Object

  • 目標屬性的類別
    =>設定SrevletContext的屬性

  • XXXXServlet
    =>繼承HttpServlet,使用目標屬性去呼叫其方法取得屬性

  • DD設定檔(web.xml)
    =>設定一個初始參數給listener,供XXXXServletContextListener使用

分類

Context只是其中一種的Listener
Listener總共有分成八種interface:

  • ServletContextAttributesListener
    內容:可確認Web應用程式Context中的屬性新增或刪除取代
    事件類型:ServletContextAttributesEvent

  • ServletContextListener
    內容:可確認Context是否被建立或是destory
    事件類型:ServletContextEvent

  • ServletRequestListener
    內容:可記錄每次的request
    事件類型:ServletRequestEvent

  • HttpSessionListener
    內容:紀錄正在活動的Session
    事件類型:HttpSessionEvent

  • HttpSessionAttributeListener
    內容:提供Session屬性被新增移除或取代的method
    事件類型:HttpSessionBindingEvent

  • HttpSessionActivationListener
    內容:提供類別Session被移到另一個JVM時(或從別的JVM移入),提供相關的method
    事件類型:HttpSessionEvent

  • HttpSessionBindingListener
    內容:當此類別物件被Bind到某個Session或是從Session移除時,提供相關的method
    事件類型:HttpSessionBindingEvent

  • ServletRequestAttributeListener
    內容:提供Request屬性被新增移除或取代的method
    事件類型:ServletRequestAttributeEvent

屬性VS.參數

  • 屬性
    一種Object,被設定在三種ServletAPI上(Context,Request,Session)
    設定的方法皆須透過物件的method
    所以在取出內容時需做轉型的動作
    較重要的部分為每個屬性存在的scope

    屬性就像被釘在佈告欄上的物件
    主要有兩個重要問題
    誰能到看到或張貼這個佈告欄?還有它能存在多久?

  • 參數
    屬於一種字串String
    設定在DD的值
    可直接透過getParameter(String s)或getInitParameter(String s)呼叫

Context屬性

Scope: WEB application的每個部分都可以使用存取
因為Context屬於全域變數的概念
意即每個Servlet(就是多個thread)都可以使用它
所以他不是thread-safe的

因此會在呼叫getServletContext()時,加上synchronized

synchronized(getServletContext()){
  getServletContext().setAttribute("XXX","XXX");
}

Request屬性

Scope: 同樣的ServletRequest才可以使用存取
只有Request是thread-safe的
會利用RequestDispatcher去做分派(使用forward方法)

ArrayList.setAttribute("xxxx",objResult);

RequestDispatcher view = request.getRequestDisoatcher("show.jsp")  
view.forward(request,response);

關於RequestDispatcher的路徑參數
在使用上也有點差異:

  • 透過ServletRequest取得
    若路徑有加上/,代表從Container的跟目錄算起
    若沒有,則會從request的同一層去找相關的JSP

    request.getRequestDispatcher("/Index.jsp").forward(request, response);
    //不管多加幾個斜線,container就是會從根目錄開始去找
    
    request.getRequestDispatcher("Index.jsp").forward(request, response);
    //會從request的同一層目錄去找對應的JSP
    
  • 透過ServletContext取得
    不能指定要不要加上斜線
    必須用/開頭表示路徑

    RequestDispatcher result = getServletContex.getRequestDispatcher("/Index.jsp");
    //必須用/開頭表示路徑
    result.forward(request, response);
    
  • forward(request, response)
    確認回應會將所有結果傳回client
    若在這之前已經先將結果傳送出去了(eg. OutputStream 的flush())
    則不能再使用此方式用forward去處理
    會得到IllegalStateException

Session屬性

Scope:同樣的HttpSession才可以使用存取
雖然Session只對一個client
但一個client有可能有多個Session(eg.開多個瀏覽器)

和Context相同,加上synchronized

synchronized(session)){
  session.setAttribute("XXX","XXX");
}

小結

今天先將此部分先簡單的做整理
後續在去做補充及實際的練習


上一篇
[Day 9 ] ServletConfig & ServletContent - part2
下一篇
[Day 11 ] Filter 簡介
系列文
30 days JSP & Servlet學習紀錄 30

尚未有邦友留言

立即登入留言