Java三大器之監(jiān)聽器(Listener)的工作原理和代碼演示

課程地址:Java三大器之監(jiān)聽器(Listener)的工作原理和代碼演示

   現(xiàn)在來說說Servlet的監(jiān)聽器Listener眉菱,它是實(shí)現(xiàn)了javax.servlet.ServletContextListener 接口的服務(wù)器端程序缴渊,它也是隨web應(yīng)用的啟動(dòng)

而啟動(dòng)绣檬,只初始化一次模狭,隨web應(yīng)用的停止而銷毀渠鸽。主要作用是:做一些初始化的內(nèi)容添加工作叫乌、設(shè)置一些基本的內(nèi)容、比如一些參數(shù)或者是一些

固定的對(duì)象等等徽缚。首先來看一下ServletContextListener接口的源代碼:

1.  public abstract interface ServletContextListener extends EventListener{  
2.  public abstract void contextInitialized(ServletContextEvent paramServletContextEvent);  
3.  public abstract void contextDestroyed(ServletContextEvent paramServletContextEvent);  
4.  }  

下面利用監(jiān)聽器對(duì)數(shù)據(jù)庫連接池DataSource的初始化演示它的使用:ListenerTest.java

1.  import javax.servlet.ServletContext;     
2.  import javax.servlet.ServletContextEvent;     
3.  import javax.servlet.ServletContextListener;     
4.  import org.apache.commons.dbcp.BasicDataSource;         
5.  /** 
6.  * 現(xiàn)在來說說Servlet的監(jiān)聽器Listener憨奸,它是實(shí)現(xiàn)了javax.servlet.ServletContextListener 接口的 
7.  * 服務(wù)器端程序,它也是隨web應(yīng)用的啟動(dòng)而啟動(dòng)凿试,只初始化一次排宰,隨web應(yīng)用的停止而銷毀似芝。主要作用是:做一些初始化 
8.  * 的內(nèi)容添加工作、設(shè)置一些基本的內(nèi)容板甘、比如一些參數(shù)或者是一些固定的對(duì)象等等党瓮。 
9.  *  
10.  * 示例代碼:使用監(jiān)聽器對(duì)數(shù)據(jù)庫連接池DataSource進(jìn)行初始化 
11.  */   
12.  public class ListenerTest implements ServletContextListener{       
13.  // 應(yīng)用監(jiān)聽器的銷毀方法     
14.  public void contextDestroyed(ServletContextEvent servletContextEvent) {     
15.  ServletContext servletContext = servletContextEvent.getServletContext();  
16.  // 在整個(gè)web應(yīng)用銷毀之前調(diào)用,將所有應(yīng)用空間所設(shè)置的內(nèi)容清空  
17.  servletContext.removeAttribute("dataSource");  
18.  System.out.println("銷毀工作完成...");    
19.  }     
20.  // 應(yīng)用監(jiān)聽器的初始化方法     
21.  public void contextInitialized(ServletContextEvent servletContextEvent) {     
22.  // 通過這個(gè)事件可以獲取整個(gè)應(yīng)用的空間     
23.  // 在整個(gè)web應(yīng)用下面啟動(dòng)的時(shí)候做一些初始化的內(nèi)容添加工作     
24.  ServletContext servletContext = servletContextEvent.getServletContext();    
25.  // 設(shè)置一些基本的內(nèi)容盐类;比如一些參數(shù)或者是一些固定的對(duì)象     
26.  // 創(chuàng)建DataSource對(duì)象寞奸,連接池技術(shù) dbcp     
27.  BasicDataSource basicDataSource = new BasicDataSource();   
28.  basicDataSource.setDriverClassName("com.jdbc.Driver");   
29.  basicDataSource.setUrl("jdbc:mysqlocalhost:3306/");   
30.  basicDataSource.setUsername("root");     
31.  basicDataSource.setPassword("root");     
32.  basicDataSource.setMaxActive(10);//最大連接數(shù)     
33.  basicDataSource.setMaxIdle(5);//最大管理數(shù)     
34.  //bds.setMaxWait(maxWait); 最大等待時(shí)間     
35.  // 把 DataSource 放入ServletContext空間中,     
36.  // 供整個(gè)web應(yīng)用的使用(獲取數(shù)據(jù)庫連接)  
37.  servletContext.setAttribute("dataSource", basicDataSource);     
38.  System.out.println("應(yīng)用監(jiān)聽器初始化工作完成...");     
39.  System.out.println("已經(jīng)創(chuàng)建DataSource...");    
40.  }     
41.  }  

web.xml中配置如下在跳,很簡單:

1.  <!-- 配置應(yīng)用監(jiān)聽器  -->     
2.  <listener>     
3.  <listener-class>com.ycq.ListenerTest</listener-class>     
4.  </listener>    

這樣配置好了之后枪萄,以后在web應(yīng)用中就可以通過ServletContext取得BasicDataSource對(duì)象,從而獲取與數(shù)據(jù)庫的連接猫妙,提高性能呻引,方便使用。

示例代碼二:

1.  import java.io.File;  
2.  import javax.servlet.ServletContextEvent;  
3.  import javax.servlet.ServletContextListener;  
4.  import com.i2f.fsp.deploy.TransactionDeployer;  
5.  /** 
6.  * 監(jiān)聽器隨著項(xiàng)目的啟動(dòng)而啟動(dòng) 
7.  * 
8.  */  
9.  public class ListenerTest2 implements ServletContextListener{  
10.  // 銷毀監(jiān)聽器   
11.  public void contextDestroyed(ServletContextEvent servletContextEvent) {  
12.  System.out.println("date20161020095500 :" + servletContextEvent.getServletContext());  
13.  }  
14.  public void contextInitialized(ServletContextEvent servletContextEvent) {  
15.  try{  
16.  // 獲取項(xiàng)目跟路徑  
17.  String basePath = servletContextEvent.getServletContext().getRealPath("/");  
18.  // D:\apache-tomcat-6.0.41\webapps\i2money\ 絕對(duì)路徑  
19.  System.out.println("basePath20161020094700 :" + basePath);  
20.  if (!(basePath.endsWith(File.separator))){  
21.  basePath = basePath + File.separator;  
22.  }  
23.  basePath = basePath + "WEB-INF" + File.separator + "classes" + File.separator;  
24.  new TransactionDeployer(basePath).deploy();  
25.  // D:\apache-tomcat-6.0.41\webapps\i2money\WEB-INF\classes\  
26.  System.out.println("basePath20161020094701 :" + basePath);  
27.  }  
28.  catch (Exception e){  
29.  e.printStackTrace();  
30.  System.exit(-1);  
31.  }  
32.  }  
33.  }  

示例代碼三:

1.  import javax.servlet.http.HttpSession;  
2.  import javax.servlet.http.HttpSessionEvent;  
3.  import javax.servlet.http.HttpSessionListener;  
4.  import org.apache.commons.logging.Log;  
5.  import org.apache.commons.logging.LogFactory;  
6.  import org.springframework.context.ApplicationContext;  
7.  import org.springframework.web.context.support.WebApplicationContextUtils;  
8.  public class UserLogoutListener implements HttpSessionListener{  
9.  protected final Log log = LogFactory.getLog(super.getClass());  
10.  public void sessionCreated(HttpSessionEvent event){  
11.  this.log.error("session created. id = " + event.getSession().getId());  
12.  }  
13.  public void sessionDestroyed(HttpSessionEvent event){  
14.  this.log.error("session destroyed.id = " + event.getSession().getId());  
15.  HttpSession session = event.getSession();  
16.  ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(session.getServletContext());  
17.  OnlineUserMonitorClient client = (OnlineUserMonitorClient)context.getBean("onlineUserMonitorClient");  
18.  client.afterSessionDestroyed(session);  
19.  }  
20.  }  

監(jiān)聽器在實(shí)際項(xiàng)目中的應(yīng)用吐咳,監(jiān)聽器在java web中應(yīng)用的較多色罚,比如:統(tǒng)計(jì)當(dāng)前在線人數(shù)、自定義session掃描器沿盅。
--------------------- 應(yīng)用一:統(tǒng)計(jì)當(dāng)前在線人數(shù) ---------------------

1.  import javax.servlet.ServletContext;  
2.  import javax.servlet.http.HttpSessionEvent;  
3.  import javax.servlet.http.HttpSessionListener;  
4.  /** 
5.  * @description HttpSessionListener監(jiān)聽器實(shí)現(xiàn)統(tǒng)計(jì)網(wǎng)站在線人數(shù)的功能 
6.  */  
7.  public class SessionListener implements HttpSessionListener{  

9.  public static int TOTAL_ONLINE_USERS = 0;  
10.  public void sessionCreated(HttpSessionEvent httpSessionEvent) {  
11.  ServletContext servletContext = httpSessionEvent.getSession().getServletContext();  
12.  TOTAL_ONLINE_USERS = (Integer) servletContext.getAttribute("TOTAL_ONLINE_USERS");  
13.  // 如果用戶退出塞帐,TOTAL_ONLINE_USERS自減1  
14.  if(TOTAL_ONLINE_USERS == 0){  
15.  servletContext.setAttribute("TOTAL_ONLINE_USERS", 1);  
16.  }  
17.  else{  
18.  TOTAL_ONLINE_USERS--;  
19.  servletContext.setAttribute("TOTAL_ONLINE_USERS", TOTAL_ONLINE_USERS);  
20.  }  
21.  }  

23.  public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {  
24.  ServletContext servletContext = httpSessionEvent.getSession().getServletContext();  
25.  TOTAL_ONLINE_USERS = (Integer) servletContext.getAttribute("TOTAL_ONLINE_USERS");  
26.  // 如果用戶登錄,TOTAL_ONLINE_USERS自增1  
27.  if(TOTAL_ONLINE_USERS == 0){  
28.  servletContext.setAttribute("TOTAL_ONLINE_USERS", 1);  
29.  }  
30.  else{  
31.  TOTAL_ONLINE_USERS++;  
32.  servletContext.setAttribute("TOTAL_ONLINE_USERS", TOTAL_ONLINE_USERS);  
33.  }  
34.  }  
35.  }  

--------------------- 應(yīng)用二:自定義session掃描器 ---------------------

1.  import java.util.LinkedList;  
2.  import java.util.List;  
3.  import java.util.Timer;  
4.  import javax.servlet.ServletContextEvent;  
5.  import javax.servlet.ServletContextListener;  
6.  import javax.servlet.http.HttpSession;  
7.  import javax.servlet.http.HttpSessionEvent;  
8.  import javax.servlet.http.HttpSessionListener;  
9.  import jeus.util.concurrent50.Collections;  
10.  /** 
11.  * @description 當(dāng)網(wǎng)站用戶量增加時(shí)沪羔,session占用的內(nèi)存會(huì)越來越大饥伊,這時(shí)session的管理,將會(huì)是一項(xiàng)很大的 
12.  * 系統(tǒng)開銷蔫饰,為了高效的管理session琅豆,我們可以寫一個(gè)監(jiān)聽器,定期清理掉過期的session 
13.  */  
14.  public class SessionScanerListener implements HttpSessionListener,ServletContextListener{  
15.  // 創(chuàng)建一個(gè)線程安全的集合篓吁,用來存儲(chǔ)session  
16.  @SuppressWarnings("unchecked")  
17.  List<HttpSession> sessionList = Collections.synchronizedList(new LinkedList<HttpSession>());  
18.  private Object lock = new Object();  

20.  public void sessionCreated(HttpSessionEvent httpSessionEvent) {  
21.  System.out.println("session 創(chuàng)建成功...");  
22.  HttpSession httpSession = httpSessionEvent.getSession();  
23.  synchronized (lock){  
24.  sessionList.add(httpSession);  
25.  }  
26.  }  

28.  public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {  
29.  System.out.println("session 銷毀成功...");  
30.  }  
31.  // web應(yīng)用關(guān)閉時(shí)觸發(fā)contextDestroyed事件  
32.  public void contextDestroyed(ServletContextEvent servletContextEvent) {  
33.  System.out.println("web應(yīng)用關(guān)閉...");  
34.  }  

36.  // web應(yīng)用啟動(dòng)時(shí)觸發(fā)contextInitialized事件  
37.  public void contextInitialized(ServletContextEvent servletContextEvent) {  
38.  System.out.println("web應(yīng)用初始化...");  
39.  // 創(chuàng)建定時(shí)器  
40.  Timer timer = new Timer();  
41.  // 每隔30秒就定時(shí)執(zhí)行任務(wù)  
42.  timer.schedule(new MyTask(sessionList,lock), 0, 1000*30);  
43.  }  
44.  }  
1.  import java.util.List;  
2.  import java.util.ListIterator;  
3.  import java.util.TimerTask;  
4.  import javax.servlet.http.HttpSession;  
5.  /** 
6.  * 定時(shí)器茫因,定義定時(shí)任務(wù)的具體內(nèi)容 
7.  */  
8.  public class MyTask extends TimerTask{  
9.  private List<HttpSession> list;  
10.  // 存儲(chǔ)傳遞過來的鎖  
11.  private Object lock;  
12.  // 構(gòu)造方法  
13.  MyTask(List<HttpSession> list, Object lock){  
14.  this.list = list;  
15.  this.lock = lock;  
16.  }  
17.  @Override  
18.  public void run() {  
19.  // 考慮到多線程的情況,這里必須要同步  
20.  synchronized (lock){  
21.  System.out.println("定時(shí)器開始執(zhí)行...");  
22.  ListIterator<HttpSession> listIterator = list.listIterator();  
23.  while(listIterator.hasNext()){  
24.  HttpSession httpSession = listIterator.next();  
25.  // httpSession.getLastAccessedTime() = session的最后訪問時(shí)間  
26.  if(System.currentTimeMillis() - httpSession.getLastAccessedTime() > 1000*30){  
27.  // 手動(dòng)銷毀session  
28.  httpSession.invalidate();  
29.  // 從集合中移除已經(jīng)被銷毀的session  
30.  listIterator.remove();  
31.  }  
32.  }  
33.  }  
34.  }  
35.  }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末杖剪,一起剝皮案震驚了整個(gè)濱河市冻押,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌盛嘿,老刑警劉巖洛巢,帶你破解...
    沈念sama閱讀 216,591評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異次兆,居然都是意外死亡稿茉,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漓库,“玉大人恃慧,你說我怎么就攤上這事∶灼唬” “怎么了糕伐?”我有些...
    開封第一講書人閱讀 162,823評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蘸嘶。 經(jīng)常有香客問我良瞧,道長,這世上最難降的妖魔是什么训唱? 我笑而不...
    開封第一講書人閱讀 58,204評(píng)論 1 292
  • 正文 為了忘掉前任褥蚯,我火速辦了婚禮,結(jié)果婚禮上况增,老公的妹妹穿的比我還像新娘赞庶。我一直安慰自己,他們只是感情好澳骤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,228評(píng)論 6 388
  • 文/花漫 我一把揭開白布歧强。 她就那樣靜靜地躺著,像睡著了一般为肮。 火紅的嫁衣襯著肌膚如雪摊册。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,190評(píng)論 1 299
  • 那天颊艳,我揣著相機(jī)與錄音茅特,去河邊找鬼。 笑死棋枕,一個(gè)胖子當(dāng)著我的面吹牛白修,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播重斑,決...
    沈念sama閱讀 40,078評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼兵睛,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了绸狐?” 一聲冷哼從身側(cè)響起卤恳,我...
    開封第一講書人閱讀 38,923評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寒矿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體若债,經(jīng)...
    沈念sama閱讀 45,334評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡符相,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,550評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片啊终。...
    茶點(diǎn)故事閱讀 39,727評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡镜豹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蓝牲,到底是詐尸還是另有隱情趟脂,我是刑警寧澤,帶...
    沈念sama閱讀 35,428評(píng)論 5 343
  • 正文 年R本政府宣布例衍,位于F島的核電站昔期,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏佛玄。R本人自食惡果不足惜硼一,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,022評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望梦抢。 院中可真熱鬧般贼,春花似錦、人聲如沸奥吩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽霞赫。三九已至腮介,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绩脆,已是汗流浹背萤厅。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留靴迫,地道東北人惕味。 一個(gè)月前我還...
    沈念sama閱讀 47,734評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像玉锌,于是被迫代替她去往敵國和親名挥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,619評(píng)論 2 354

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