- package com.listeners;
- import javax.servlet.ServletContextListener;
- import javax.servlet.ServletContextEvent;
- import javax.servlet.*;
- public class MyContextListener implements ServletContextListener {
- private ServletContext context = null;
- public void contextDestroyed(ServletContextEvent event){
- //Output a simple message to the server's console
- System.out.println("The Simple Web App. Has Been Removed");
- this.context = null;
- }
- // 這個方法在Web應用服務做好接受請求的時候被調用。
- public void contextInitialized(ServletContextEvent event){
- this.context = event.getServletContext();
- //Output a simple message to the server's console
- System.out.println("The Simple Web App. Is Ready");
- }
- }
- package com.listeners;
- import javax.servlet.ServletContextListener;
- import javax.servlet.ServletContextEvent;
- import javax.servlet.*;
- public class MyContextListener implements ServletContextListener {
- private ServletContext context = null;
- public void contextDestroyed(ServletContextEvent event){
- //Output a simple message to the server's console
- System.out.println("The Simple Web App. Has Been Removed");
- this.context = null;
- }
- // 這個方法在Web應用服務做好接受請求的時候被調用。
- public void contextInitialized(ServletContextEvent event){
- this.context = event.getServletContext();
- //Output a simple message to the server's console
- System.out.println("The Simple Web App. Is Ready");
- }
- }
package com.listeners; import javax.servlet.ServletContextListener; import javax.servlet.ServletContextEvent; import javax.servlet.*; public class MyContextListener implements ServletContextListener { private ServletContext context = null; public void contextDestroyed(ServletContextEvent event){ //Output a simple message to the server's console System.out.println("The Simple Web App. Has Been Removed"); this.context = null; } // 這個方法在Web應用服務做好接受請求的時候被調用。 public void contextInitialized(ServletContextEvent event){ this.context = event.getServletContext(); //Output a simple message to the server's console System.out.println("The Simple Web App. Is Ready"); } }
在WEB.XML中
- <web-app>
- <listener>
- <listener-class>
- com.listeners.MyContextListener
- </listener-class>
- </listener>
- <servlet/>
- <servlet-mapping/>
- </web-app>
- <web-app>
- <listener>
- <listener-class>
- com.listeners.MyContextListener
- </listener-class>
- </listener>
- <servlet/>
- <servlet-mapping/>
- </web-app>
<web-app> <listener> <listener-class> com.listeners.MyContextListener </listener-class> </listener> <servlet/> <servlet-mapping/> </web-app>
ServletContextListener接口有兩方需要實現的方法:
contextInitialized()和contextDestroyed();
Listener,譯為監聽者.顧名思義,它會監聽Servlet容器,當應用開始的時候它會調用contextInitialized()方法;
當應用關閉的時候,它同樣會調用contextDestroyed()方法.
我們可以利用這個特性初始化一些信息,當然我們也可以利用Servlet類init()方法,並在配置文件中讓它啟動應用的時候
就執行,並且在關閉的時候執行destroy()方法.但是繼承此接口應該更符合容器的應用.
舉個簡單的例子:在一些論壇,社區及聊天室當中,刪除在線的超時用戶就可以利用這個接口來實現.
可以利用JAVA的TimerTask及Timer類來實現每隔一定的時間進行自動檢測.
實例代碼如下:
UserOnlineTimerTask.java
- package com.bcxy.servlet;
- import java.util.TimerTask;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- public class UserOnlineTimerTask extends TimerTask {
- Log log = LogFactory.getLog(UserOnlineTimerTask.class);
- public void run() {
- // 刪除超時在線用戶
- log.info("刪除在線的超時用戶....");
- }
- }
- package com.bcxy.servlet;
- import java.util.TimerTask;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- public class UserOnlineTimerTask extends TimerTask {
- Log log = LogFactory.getLog(UserOnlineTimerTask.class);
- public void run() {
- // 刪除超時在線用戶
- log.info("刪除在線的超時用戶....");
- }
- }
package com.bcxy.servlet; import java.util.TimerTask; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class UserOnlineTimerTask extends TimerTask { Log log = LogFactory.getLog(UserOnlineTimerTask.class); public void run() { // 刪除超時在線用戶 log.info("刪除在線的超時用戶...."); } }
SysListener.java
- package com.bcxy.servlet;
- import java.io.IOException;
- import java.util.Timer;
- import javax.servlet.ServletContextEvent;
- import javax.servlet.ServletContextListener;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServlet;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- public class SysListener
- extends HttpServlet
- implements ServletContextListener {
- Log log = LogFactory.getLog(SysListener.class);
- Timer timer = new Timer();
- public void service(ServletRequest request, ServletResponse response)
- throws ServletException, IOException {
- //
- }
- public void contextInitialized(ServletContextEvent sce) {
- log.info("initial context....");
- timer.schedule(new UserOnlineTimerTask(), 0, 10000);
- }
- public void contextDestroyed(ServletContextEvent sce) {
- log.info("destory context....");
- timer.cancel();
- }
- }
- package com.bcxy.servlet;
- import java.io.IOException;
- import java.util.Timer;
- import javax.servlet.ServletContextEvent;
- import javax.servlet.ServletContextListener;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServlet;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- public class SysListener
- extends HttpServlet
- implements ServletContextListener {
- Log log = LogFactory.getLog(SysListener.class);
- Timer timer = new Timer();
- public void service(ServletRequest request, ServletResponse response)
- throws ServletException, IOException {
- //
- }
- public void contextInitialized(ServletContextEvent sce) {
- log.info("initial context....");
- timer.schedule(new UserOnlineTimerTask(), 0, 10000);
- }
- public void contextDestroyed(ServletContextEvent sce) {
- log.info("destory context....");
- timer.cancel();
- }
- }
package com.bcxy.servlet; import java.io.IOException; import java.util.Timer; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class SysListener extends HttpServlet implements ServletContextListener { Log log = LogFactory.getLog(SysListener.class); Timer timer = new Timer(); public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { // } public void contextInitialized(ServletContextEvent sce) { log.info("initial context...."); timer.schedule(new UserOnlineTimerTask(), 0, 10000); } public void contextDestroyed(ServletContextEvent sce) { log.info("destory context...."); timer.cancel(); } }
如果你沒有使用log4j的話,你可以把log.info()改為System.out.println()會得到同樣的結果.
在Servlet API中有一個ServletContextListener接口,它能夠監聽ServletContext對象的生命周期,實際上就是監聽Web應用的生命周期。
當Servlet容器啟動或終止Web應用時,會觸發ServletContextEvent事件,該事件由 ServletContextListener 來處理。在 ServletContextListener 接口中定義了處理ServletContextEvent事件的兩個方法。
contextInitialized(ServletContextEvent sce):當Servlet容器啟動Web應用時調用該方法。在調用完該方法之后,容器再對Filter初始化,並且對那些在Web應用啟動時就需要被初始化的Servlet進諧跏薊?/P>
contextDestroyed(ServletContextEvent sce):當Servlet容器終止Web應用時調用該方法。在調用該方法之前,容器會先銷毀所有的Servlet和Filter過濾器。
下面通過一個例子來介紹ServletContextListener的用法。本章4.4.1節的例程4-9的CounterServlet類只能統計當Web應用啟動后,網頁被客戶端訪問的次數。如果重新啟動Web應用,計數器又會重新從1開始統計訪問次數。在實際應用中,往往需要統計自Web應用被發布后網頁被客戶端訪問的次數,這就要求當Web應用被終止時,計數器的數值被永久存儲在一個文件中或者數據庫中,等到Web應用重新啟動時,先從文件或數據庫中讀取計數器的初始值,然后在此基礎上繼續計數。
向文件中寫入或讀取計數器的數值的功能可以由自定義的 MyServletContextListener類(參見例程4-11)來完成,它具有以下功能:
在 Web 應用啟動時從文件中讀取計數器的數值,並把表示計數器的 Counter對象存放到 Web 應用范圍內。存放計數器的文件的路徑為helloapp/count/count.txt。
在Web應用終止時把Web應用范圍內的計數器的數值保存到count.txt文件中。
例程4-11 MyServletContextListener.java
public class MyServletContextListener implements ServletContextListener{ public void contextInitialized(ServletContextEvent sce){ System.out.println("helloapp application is Initialized."); //獲取ServletContext對象 ServletContext context=sce.getServletContext(); try{ //從文件中讀取計數器的數值 BufferedReader reader=new BufferedReader( new InputStreamReader(context. getResourceAsStream("/count/count.txt"))); int count=Integer.parseInt(reader.readLine()); reader.close(); //創建計數器對象 Counter counter=new Counter(count); //把計數器對象保存到Web應用范圍 context.setAttribute("counter",counter); }catch(IOException e){e.printStackTrace();} } public void contextDestroyed(ServletContextEvent sce){ System.out.println("helloapp application is Destroyed."); //獲取ServletContext對象 ServletContext context=sce.getServletContext(); //從Web應用范圍獲得計數器對象 Counter counter=(Counter)context.getAttribute("counter"); if(counter!=null){ try{ //把計數器的數值寫到count.txt文件中 String filepath=context.getRealPath("/count"); filepath=filepath+"/count.txt"; PrintWriter pw=new PrintWriter(filepath); pw.println(counter.getCount()); pw.close(); }catch(IOException e){e.printStackTrace();} } } } |
用戶自定義的MyServletContextListener監聽器只有先向Servlet容器注冊,Servlet容器在啟動或終止Web應用時,才會調用該監聽器的相關方法。在web.xml文件中,<listener>元素用於向容器注冊監聽器:
Tips <listener> <listener-class>mypack.MyServletContextListener<listener-class /> </listener> |
下面按如下步驟演示MyServletContextListener監聽器的作用。
(1)在helloapp/count目錄下創建count.txt文件,在該文件中存放了一個數字“5”。
(2)啟動 Tomcat。在瀏覽器中通過 http://localhost:8080/helloapp/counter 訪問CounterServlet,在第一次訪問該Servlet時,瀏覽器端顯示計數器的值為5。
(3)刷新上述訪問 CounterServlet 的頁面,會看到每刷新一次,計數器的值增加1,假定最后一次刷新后的計數器的值為10。
(4)手工終止helloapp應用。查看helloapp/count/count.txt文件,會發現在該文件中存放的數字變為10。
(5)手工重新啟動 helloapp 應用。在瀏覽器中再次訪問 CounterServlet,當第一次訪問該Servlet時,瀏覽器端顯示計數器的值為10。
從上述實驗中可以看出,MyServletContextListener 監聽器與 CounterServlet 共享Web應用范圍內的代表計數器的Counter對象。監聽器在Web應用啟動或終止時會操縱Counter對象,而Servlet在每次響應客戶請求時會操縱Counter對象。
觀察MyServletContextListener及本章4.3.4節的名為lifeInit的 LifeServlet在 Tomcat 控制台的打印結果的先后順序,會發現當 Web 應用啟動時,Servlet容器先調用MyServletContextListener的contextInitialized()方法,再調用lifeInit的init()方法;當Web應用終止時,Servlet容器先調用lifeInit的destroy()方法,再調用MyServletContextListener的contextDestroyed()方法。由此可見,在Web應用的生命周期中,ServletContext對象最早被創建,最晚被銷毀
ServletContextListener接口有兩方需要實現的方法:contextInitialized()和contextDestroyed();
Listener,譯為監聽者.顧名思義,它會監聽Servlet容器,當應用開始的時候它會調用contextInitialized()方法;
當應用關閉的時候,它同樣會調用contextDestroyed()方法.我們可以利用這個特性初始化一些信息,當然我們
也可以利用Servlet類init()方法,並在配置文件中讓它啟動應用的時候就執行,並且在關閉的時候執行destroy()方
法.但是繼承此接口應該更符合容器的應用