ServletContextListener使用詳解

【轉(zhuǎn)自】http://blog.csdn.net/zhaozheng7758/article/details/6103700

在 Servlet API 中有一個(gè) ServletContextListener 接口能曾,它能夠監(jiān)聽 ServletContext 對象的生命周期,實(shí)際上就是監(jiān)聽 Web 應(yīng)用的生命周期亚亲。

當(dāng)Servlet 容器啟動(dòng)或終止Web 應(yīng)用時(shí)股缸,會(huì)觸發(fā)ServletContextEvent 事件果元,該事件由 ServletContextListener 來處理。在 ServletContextListener 接口中定義了處理ServletContextEvent 事件的兩個(gè)方法。

l contextInitialized(ServletContextEvent sce) :當(dāng)Servlet 容器啟動(dòng)Web 應(yīng)用時(shí)調(diào)用該方法昧捷。在調(diào)用完該方法之后牲平,容器再對Filter 初始化堤框,并且對那些在Web 應(yīng)用啟動(dòng)時(shí)就需要被初始化的Servlet 進(jìn)行初始化。

l contextDestroyed(ServletContextEvent sce) :當(dāng)Servlet 容器終止Web 應(yīng)用時(shí)調(diào)用該方法。在調(diào)用該方法之前蜈抓,容器會(huì)先銷毀所有的Servlet 和Filter 過濾器启绰。

下面通過兩個(gè)具體的例子來介紹 ServletContextListener 的用法。

例一:在服務(wù)啟動(dòng)時(shí)沟使,將數(shù)據(jù)庫中的數(shù)據(jù)加載進(jìn)內(nèi)存委可,并將其賦值給一個(gè)屬性名,其它的 Servlet 就可以通過 getAttribute 進(jìn)行屬性值的訪問腊嗡。有如下兩個(gè)步驟:

1 : ServletContext 對象是一個(gè)為整個(gè) web 應(yīng)用提供共享的內(nèi)存着倾,任何請求都可以訪問里面的內(nèi)容

2 :如何實(shí)現(xiàn)在服務(wù)啟動(dòng)的時(shí)候就動(dòng)態(tài)的加入到里面的內(nèi)容:我們需要做的有:

1 ) 實(shí)現(xiàn) servletContextListerner 接口 并將要共享的通過 setAttribute ( name,data )方法提交到內(nèi)存中去 ;

2 )應(yīng)用項(xiàng)目通過 getAttribute(name) 將數(shù)據(jù)取到 燕少。

package ServletContextTest; 

 

import java.sql.Connection; 

import java.sql.PreparedStatement; 

import java.sql.ResultSet; 

import java.util.HashMap; 

import java.util.Map; 

 

import javax.servlet.ServletContext; 

import javax.servlet.ServletContextEvent; 

import javax.servlet.ServletContextListener; 

 

import util.ConnectTool; 

 

public class ServletContextLTest implements ServletContextListener{ 

    // 實(shí)現(xiàn)其中的銷毀函數(shù)

    public void contextDestroyed(ServletContextEvent sce) { 

        System.out.println("this is last destroyeed");    

    } 

    // 實(shí)現(xiàn)其中的初始化函數(shù)卡者,當(dāng)有事件發(fā)生時(shí)即觸發(fā)

    public void contextInitialized(ServletContextEvent sce) { 

        ServletContext sct=sce.getServletContext(); 

        Map<Integer,String> depts=new HashMap<Integer,String>(); 

        Connection connection=null; 

        PreparedStatement pstm=null; 

        ResultSet rs=null; 

         

        try{ 

            connection=ConnectTool.getConnection(); 

            String sql="select deptNo,dname from dept"; 

            pstm=connection.prepareStatement(sql); 

            rs=pstm.executeQuery(); 

            while(rs.next()){ 

                depts.put(rs.getInt(1), rs.getString(2)); 

            } 

            // 將所取到的值存放到一個(gè)屬性鍵值對中

            sct.setAttribute("dept", depts); 

            System.out.println("======listener test is beginning========="); 

        }catch(Exception e){ 

            e.printStackTrace(); 

        }finally{ 

            ConnectTool.releasersc(rs, pstm, connection); 

        } 

    } 

} 

在完成上述編碼后,仍需在 web.xml 中進(jìn)行如下配置客们,以使得該監(jiān)聽器可以起作用崇决。

<listener> 

   <listener-class>ServletContextTest.ServletContextLTest</listener-class> 

</listener> 

在完成上述配置后, web 服務(wù)器在啟動(dòng)時(shí)底挫,會(huì)直接加載該監(jiān)聽器恒傻,通過以下的應(yīng)用程序就可以進(jìn)行數(shù)據(jù)的訪問。

package ServletContextTest; 

import java.io.IOException; 

import java.io.PrintWriter; 

import java.util.*; 

import javax.servlet.ServletContext; 

import javax.servlet.ServletException; 

import javax.servlet.http.HttpServlet; 

import javax.servlet.http.HttpServletRequest; 

import javax.servlet.http.HttpServletResponse; 

public class CreateEmployee extends HttpServlet{ 

 

    @Override 

    protected void service(HttpServletRequest request, HttpServletResponse response) 

            throws ServletException, IOException { 

        ServletContext sct=getServletConfig().getServletContext(); 

// 從上下文環(huán)境中通過屬性名獲取屬性值

        Map<Integer,String> dept=(Map<Integer,String>)sct.getAttribute("dept"); 

        Set<Integer> key=dept.keySet(); 

        response.setContentType("text/html;charset=utf-8"); 

        PrintWriter out=response.getWriter(); 

        out.println("<html>"); 

        out.println("<body>"); 

        out.println("<form action='/register' action='post'>"); 

        out.println("<table alignb='center'>"); 

        out.println("<tr>"); 

        out.println("<td>"); 

        out.println("username:"); 

        out.println("</td>"); 

        out.println("<td>"); 

        out.println("<input type='text' name='username'"); 

        out.println("</tr>"); 

        out.println("<tr>"); 

        out.println("<td>"); 

        out.println("city:"); 

        out.println("</td>"); 

        out.println("<td>"); 

        out.println("<select name='dept'"); 

        for(Integer i:key){ 

            out.println("<option value='"+i+"'>"+dept.get(i)+"</option>"); 

        } 

        out.println("</select>"); 

        out.println("</td>"); 

        out.println("<tr>"); 

        out.println("</table>"); 

        out.println("</form>"); 

        out.println("</body>"); 

        out.println("</html>"); 

        out.flush(); 

    } 

} 

例二:書寫一個(gè)類用于統(tǒng)計(jì)當(dāng)Web 應(yīng)用啟動(dòng)后建邓,網(wǎng)頁被客戶端訪問的次數(shù)碌冶。如果重新啟動(dòng)Web 應(yīng)用,計(jì)數(shù)器不會(huì)重新從1 開始統(tǒng)計(jì)訪問次數(shù)涝缝,而是從上次統(tǒng)計(jì)的結(jié)果上進(jìn)行累加扑庞。在實(shí)際應(yīng)用中,往往需要統(tǒng)計(jì)自Web 應(yīng)用被發(fā)布后網(wǎng)頁被客戶端訪問的次數(shù)拒逮,這就要求當(dāng)Web 應(yīng)用被終止時(shí)罐氨,計(jì)數(shù)器的數(shù)值被永久存儲(chǔ)在一個(gè)文件中或者數(shù)據(jù)庫中,等到Web 應(yīng)用重新啟動(dòng)時(shí)滩援,先從文件或數(shù)據(jù)庫中讀取計(jì)數(shù)器的初始值栅隐,然后在此基礎(chǔ)上繼續(xù)計(jì)數(shù)。

向文件中寫入或讀取計(jì)數(shù)器的數(shù)值的功能可以由自定義的 MyServletContextListener 類來完成玩徊,它具有以下功能:

1 租悄、在 Web 應(yīng)用啟動(dòng)時(shí)從文件中讀取計(jì)數(shù)器的數(shù)值,并把表示計(jì)數(shù)器的 Counter 對象存放到 Web 應(yīng)用范圍內(nèi)恩袱。存放計(jì)數(shù)器的文件的路徑為helloapp/count/count.txt 泣棋。

2 、在Web 應(yīng)用終止時(shí)把Web 應(yīng)用范圍內(nèi)的計(jì)數(shù)器的數(shù)值保存到count.txt 文件中畔塔。

package ServletContextTest; 

import javax.servlet.ServletContext; 

import javax.servlet.ServletContextEvent; 

import javax.servlet.ServletContextListener; 

public class MyServletContextListener implements ServletContextListener{

  public void contextInitialized(ServletContextEvent sce){

    System.out.println("helloapp application is Initialized.");

    // 獲取 ServletContext 對象

    ServletContext context=sce.getServletContext();

    try{

       // 從文件中讀取計(jì)數(shù)器的數(shù)值

       BufferedReader reader=new BufferedReader(

           new InputStreamReader(context.

           getResourceAsStream("/count/count.txt")));

       int count=Integer.parseInt(reader.readLine());

       reader.close();

       // 創(chuàng)建計(jì)數(shù)器對象

       Counter counter=new Counter(count);

       // 把計(jì)數(shù)器對象保存到 Web 應(yīng)用范圍

       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 應(yīng)用范圍獲得計(jì)數(shù)器對象

       Counter counter=(Counter)context.getAttribute("counter");

       if(counter!=null){

       try{

          // 把計(jì)數(shù)器的數(shù)值寫到 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 監(jiān)聽器在 Servlet 容器進(jìn)行注冊潭辈, Servlet 容器會(huì)在啟動(dòng)或終止 Web 應(yīng)用時(shí)鸯屿,會(huì)調(diào)用該監(jiān)聽器的相關(guān)方法。在 web.xml 文件中把敢, <listener> 元素用于向容器注冊監(jiān)聽器:

<listener>
<listener-class> ServletContextTest .MyServletContextListener<listener-class />
</listener>

通過上述兩個(gè)例子寄摆,即可以非常清楚的了解到 ServletContextListener 接口的使用方法及技巧。 在Container 加載Web 應(yīng)用程序時(shí)(例如啟動(dòng) Container 之后)修赞,會(huì)呼叫contextInitialized() 婶恼,而當(dāng)容器移除Web 應(yīng)用程序時(shí),會(huì)呼叫contextDestroyed () 方法柏副。 通過 Tomcat 控制臺(tái)的打印結(jié)果的先后順序熙尉,會(huì)發(fā)現(xiàn)當(dāng) Web 應(yīng)用啟動(dòng)時(shí),Servlet 容器先調(diào)用contextInitialized() 方法搓扯,再調(diào)用lifeInit 的init() 方法;當(dāng)Web 應(yīng)用終止時(shí)包归,Servlet 容器先調(diào)用lifeInit 的destroy() 方法锨推,再調(diào)用contextDestroyed() 方法。由此可見公壤,在Web 應(yīng)用的生命周期中换可,ServletContext 對象最早被創(chuàng)建,最晚被銷毀厦幅。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沾鳄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子确憨,更是在濱河造成了極大的恐慌译荞,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件休弃,死亡現(xiàn)場離奇詭異吞歼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)塔猾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門篙骡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丈甸,你說我怎么就攤上這事糯俗。” “怎么了睦擂?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵得湘,是天一觀的道長。 經(jīng)常有香客問我顿仇,道長忽刽,這世上最難降的妖魔是什么天揖? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮跪帝,結(jié)果婚禮上今膊,老公的妹妹穿的比我還像新娘。我一直安慰自己伞剑,他們只是感情好斑唬,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著黎泣,像睡著了一般恕刘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抒倚,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天褐着,我揣著相機(jī)與錄音,去河邊找鬼托呕。 笑死含蓉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的项郊。 我是一名探鬼主播馅扣,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼着降!你這毒婦竟也來了差油?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤任洞,失蹤者是張志新(化名)和其女友劉穎蓄喇,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體交掏,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡公罕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耀销。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片楼眷。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖熊尉,靈堂內(nèi)的尸體忽然破棺而出罐柳,到底是詐尸還是另有隱情,我是刑警寧澤狰住,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布张吉,位于F島的核電站,受9級(jí)特大地震影響催植,放射性物質(zhì)發(fā)生泄漏肮蛹。R本人自食惡果不足惜勺择,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伦忠。 院中可真熱鬧省核,春花似錦、人聲如沸昆码。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赋咽。三九已至旧噪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間脓匿,已是汗流浹背淘钟。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留陪毡,地道東北人米母。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像缤骨,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子尺借,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在绊起,面了一些公司,掛了不少燎斩,但最終還是拿到小米虱歪、百度、阿里栅表、京東笋鄙、新浪、CVTE怪瓶、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,209評論 11 349
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理萧落,服務(wù)發(fā)現(xiàn),斷路器洗贰,智...
    卡卡羅2017閱讀 134,629評論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,773評論 6 342
  • 1.內(nèi)存泄露 內(nèi)存泄漏兩種情況: 在堆中申請的空間沒有被釋放(虛擬機(jī)gc可以解決) 對象已不在使用找岖,但仍然在內(nèi)存中...
    Aimerwhy閱讀 582評論 0 0
  • 這部分主要是與Java Web和Web Service相關(guān)的面試題。 96敛滋、闡述Servlet和CGI的區(qū)別? 答...
    雜貨鋪老板閱讀 1,400評論 0 10