1. 程式人生 > >spring專案中監聽器作用-ContextLoaderListener

spring專案中監聽器作用-ContextLoaderListener

作用:在啟動Web 容器時,自動裝配Spring applicationContext.xml 的配置資訊。

因為它實現了ServletContextListener 這個介面,在web.xml 配置這個監聽器,啟動容器時,就會預設執行它實現的方法。在ContextLoaderListener 中關聯了ContextLoader 這個類,所以整個載入配置過程由ContextLoader 來完成

spring 在 web 下的入口在配置檔案 web.xml 的監聽器中

< listener >

        < listener-class >

           org.springframework.web.context.ContextLoaderListener

        </ listener-class >

</ listener >

<context-param>

     <param-name>contextConfigLocation</param-name>

      <param-value>classpath:conf/spring/applicationContext.xml</param-value>

</context-param>

上述是在web.xml 中的配置資訊。

// 實現了介面 ServletContextListener,

也就是說他必須實現 contextDestroyed, contextInitialized 這兩個方法

public class ContextLoaderListener implements ServletContextListener {

       private ContextLoader contextLoader;

       /**

       * Initialize the root web application context.

       */

//Spring 框架由此啟動 , contextInitialized 也就是監聽器類的 main 入口函式

       public void contextInitialized (ServletContextEvent event) {

              this.contextLoader = createContextLoader();

              this.contextLoader.initWebApplicationContext(event.getServletContext());

       }

       /**

       * Create the ContextLoader to use. Can be overridden in subclasses.

       * @return the new ContextLoader

       */                                            

       protected ContextLoader createContextLoader() {

              return new ContextLoader();

       }

       /**

       * Return the ContextLoader used by this listener.

       * @return the current ContextLoader

       */

       public ContextLoader getContextLoader() {

              return this.contextLoader;

       }

       /**

       * Close the root web application context.

       */

       public void contextDestroyed (ServletContextEvent event) {

              if (this.contextLoader != null) {

                     this.contextLoader.closeWebApplicationContext(event.getServletContext());

              }

       }

}

總的來說這個入口非常簡單 , 所有實現都隱藏在 ContextLoader 類裡 , 我們在下一篇的內容中討論 ContextLoader, 如果你不知道為什麼這裡是程式的入口 , 那麼複習一下 ServletContextListener 介面和監聽器的相關知識吧

   ServletContext 被 Servlet 程式用來與 Web 容器通訊。例如寫日誌,轉發請求。每一個 Web 應用程式含有一個Context ,被Web 應用內的各個程式共享。因為Context 可以用來儲存資源並且共享,所以我所知道的 ServletContext 的最大應用是Web 快取---- 把不經常更改的內容讀入記憶體,所以伺服器響應請求的時候就不需要進行慢速的磁碟I/O 了。

   ServletContextListener 是 ServletContext 的監聽者,如果 ServletContext 發生變化,如伺服器啟動時 ServletContext 被建立,伺服器關閉時 ServletContext 將要被銷燬。

       在JSP 檔案中,application 是 ServletContext 的例項,由JSP 容器預設建立。Servlet 中呼叫 getServletContext() 方法得到 ServletContext 的例項。

我們使用快取的思路大概是:

       1. 伺服器啟動時,ServletContextListener 的 contextInitialized() 方法被呼叫,所以在裡面建立好快取。可以從檔案中或者從資料庫中讀取取快取內容生成類,用 ervletContext.setAttribute() 方法將快取類儲存在 ServletContext 的例項中。

       2. 程式使用 ServletContext.getAttribute() 讀取快取。如果是 JSP ,使用a pplication.getAttribute() 。如果是 Servlet ,使用 getServletContext().getAttribute() 。如果快取發生變化( 如訪問計數) ,你可以同時更改快取和檔案/ 資料庫。或者你等 變化積累到一定程式再儲存,也可以在下一步儲存。

       3. 伺服器將要關閉時,ServletContextListener 的 contextDestroyed() 方法被呼叫,所以在裡面儲存快取的更改。將更改後的快取儲存迴文件或者資料庫,更新原來的內容。

Java 程式碼  

  1. import User; //my own   
  2. classimport DatabaseManager; // my own class  
  3. import javax.servlet.ServletContext;  
  4. import javax.servlet.ServletContextListener;  
  5. public class MyContextListener  implements ServletContextListener {      
  6.       private ServletContext context = null;      
  7.       public void contextInitialized(ServletContextEvent event) {     
  8.                 context = event.getServletContext();          
  9.                 User user = DatabaseManager.getUserById(1);       
  10.                 context.setAttribute("user1", user);      
  11.       }   
  12.       public void contextDestroyed(ServletContextEvent event) {   
  13.                  User user = (User)context.getAttribute("user1");         
  14.                  DatabaseManager.updateUserData(user);        
  15.                  this.context = null;     
  16.       }  
  17. }  

import User; //my own

classimport DatabaseManager; // my own class

import javax.servlet.ServletContext;

import javax.servlet.ServletContextListener;

public class MyContextListener  implements ServletContextListener {   

      private ServletContext context = null;

      public void contextInitialized(ServletContextEvent event) {

                context = event.getServletContext(); 

                User user = DatabaseManager.getUserById(1); 

                context.setAttribute("user1", user);

      }

      public void contextDestroyed(ServletContextEvent event) {

                 User user = (User)context.getAttribute("user1"); 

                 DatabaseManager.updateUserData(user); 

                 this.context = null;

      }

}

佈署 ServletContextListener

      你實現(implements) 了 ServletContextListener 編譯後,把它放在正確的WEB-INF/classes 目錄下,更改WEB-INF 目錄下的 web.xml 檔案,在web-app 節點裡新增

<listener>

        <listener-class>MyServletContextListener</listener-class>

</listener>