spring專案中監聽器作用-ContextLoaderListener
因為它實現了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,
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 程式碼
- 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;
- }
- }
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>