利用Servlet监听器实现简单网站访问量和在线人数统计
轉(zhuǎn)自 http://blog.sina.com.cn/s/blog_621a42970100gblw.html?
Servlet監(jiān)聽器主要有三種,在ServletContext(上下文對(duì)象)、Session(會(huì)話)和request(請(qǐng)求)這三對(duì)象上進(jìn)行監(jiān)聽,可以監(jiān)聽對(duì)象的創(chuàng)建、銷毀、添加屬性、刪除屬性、屬性值的改變等。ServletContext對(duì)象的作用域在整個(gè)WEB應(yīng)用程序,類似于Static屬性;Session的作用域在一個(gè)會(huì)話,一個(gè)會(huì)話可以理解為一個(gè)從一個(gè)瀏覽器發(fā)出請(qǐng)求到服務(wù)器開始,一直到瀏覽器關(guān)閉(但通常我們可以設(shè)置會(huì)話的生命期,防止那些獲得連接后卻長(zhǎng)時(shí)間沒有再向服務(wù)器發(fā)出請(qǐng)求的情況),相當(dāng)于類的成員變量;request的作用域僅在一次請(qǐng)求,即瀏覽器發(fā)送一次請(qǐng)求到服務(wù)器處理該請(qǐng)求并發(fā)回響應(yīng)就結(jié)束了,相當(dāng)于局部變量。
????要實(shí)現(xiàn)統(tǒng)計(jì)網(wǎng)站的歷史訪問量就要利用ServletContext的全局屬性的特點(diǎn)了,為了在服務(wù)器停止后,之前的訪問量不會(huì)消失,我們就應(yīng)該在服務(wù)器關(guān)閉前將當(dāng)前的訪問量存放到文件里面,以便下一次重啟服務(wù)器后,可以繼續(xù)使用。在ServletContext上面創(chuàng)建監(jiān)聽器,監(jiān)聽上下文對(duì)象的銷毀和創(chuàng)建,并同時(shí)在創(chuàng)建上下文的時(shí)候從文件讀取歷史數(shù)據(jù),在上下文銷毀的時(shí)候?qū)?dāng)前訪問量寫入到文件保存起來(lái)。以后每當(dāng)創(chuàng)建一個(gè)會(huì)話(Session)的時(shí)候,就將當(dāng)前的計(jì)數(shù)值加一。在線人數(shù)的統(tǒng)計(jì)是利用在創(chuàng)建會(huì)話的時(shí)候,將在線人數(shù)之加一,在會(huì)話對(duì)象銷毀的時(shí)候,將在線人數(shù)值減一。因?yàn)閮煞N人數(shù)統(tǒng)計(jì)都是被所有用戶共享的信息,所以使用ServletContext的setAttribute()和getAttribut()方法來(lái)對(duì)總?cè)藬?shù)和在線人數(shù)進(jìn)行管理。
????創(chuàng)建對(duì)上下文對(duì)象的監(jiān)聽器:
public class ContextListener implements ServletContextListener{
?public void contextDestroyed(ServletContextEvent arg0) {
??// TODO Auto-generated method stub
??Properties pro = new Properties();??
??try {
???pro.setProperty("counter", arg0.getServletContext().getAttribute("counter").toString());
???String filePath = arg0.getServletContext().getRealPath("/WEB-INF/classes/db/count.txt");
//上下文對(duì)象銷毀時(shí),將當(dāng)前訪問量寫入文件
???OutputStream os = new FileOutputStream(filePath);
???pro.store(os, null);
??} catch (IOException e) {
???// TODO Auto-generated catch block
???e.printStackTrace();
??}
??
?}
?public void contextInitialized(ServletContextEvent arg0) {
??// TODO Auto-generated method stub
??arg0.getServletContext().setAttribute("online", 0);
??Properties pro = new Properties();
??InputStream in = ContextListener.class.getResourceAsStream("/db/count.txt");
??String n = null;
??try {
???pro.load(in);
???n = pro.getProperty("counter");//從計(jì)數(shù)文件中讀取該站的歷史訪問量
???arg0.getServletContext().setAttribute("counter", Integer.parseInt(pro.getProperty("counter")));
??} catch (IOException e) {
???// TODO Auto-generated catch block
???System.out.println("讀取計(jì)數(shù)文件失敗");
??}
??System.out.println("創(chuàng)建上下文對(duì)象" + n);
?}
}
?創(chuàng)建對(duì)會(huì)話對(duì)象的監(jiān)聽:
public class SessionListener implements HttpSessionListener{
?public void sessionCreated(HttpSessionEvent arg0) {
??// TODO Auto-generated method stub
???HttpSession session = arg0.getSession();
??int i = (Integer)session.getServletContext().getAttribute("online");//獲得當(dāng)前在線人數(shù),并將其加一
??session.getServletContext().setAttribute("online", i+1);
??int n = (Integer)session.getServletContext().getAttribute("counter");//創(chuàng)建一個(gè)會(huì)話就將訪問量加一
??session.getServletContext().setAttribute("counter", n+1);
??Properties pro = new Properties();??
??try {//訪問人數(shù)加一后就將結(jié)果寫入文件(防止不正常關(guān)閉服務(wù)器)
???pro.setProperty("counter", session.getServletContext().getAttribute("counter").toString());
???String filePath = session.getServletContext().getRealPath("/WEB-INF/classes/db/count.txt");
???OutputStream os = new FileOutputStream(filePath);
???pro.store(os, null);
??} catch (IOException e) {
???// TODO Auto-generated catch block
???System.out.println("寫入計(jì)數(shù)文件失敗");
??}
??System.out.println("創(chuàng)建一個(gè)會(huì)話");
?}
?public void sessionDestroyed(HttpSessionEvent arg0) {
??// TODO Auto-generated method stub
??//銷毀會(huì)話的時(shí)候,需要將在線人數(shù)減一
??ServletContext context = arg0.getSession().getServletContext();
??Integer i = (Integer)context.getAttribute("online");
??context.setAttribute("online", i-1);
??arg0.getSession().invalidate();
??System.out.println("銷毀一個(gè)會(huì)話");
?}
}?
???在web.xml文件中將監(jiān)聽器注冊(cè),在創(chuàng)建和銷毀對(duì)象時(shí)就會(huì)觸發(fā)該事件了。?因?yàn)槲覀兺ǔW鰷y(cè)試的時(shí)候,服務(wù)器的關(guān)閉是沒有通過正常的方式來(lái)進(jìn)行的,所以程序中在創(chuàng)建一個(gè)會(huì)的時(shí)候?qū)⒕W(wǎng)站歷史訪問數(shù)據(jù)值加一后就將該值在文件中進(jìn)行更新,否則可能該值不會(huì)改變。創(chuàng)建一個(gè)會(huì)話是通過request.getSession()來(lái)觸發(fā)的,所以在做測(cè)試的Servlet中需要加上HttpSession session = request.getSession();
??//設(shè)置會(huì)話的最大不活動(dòng)時(shí)間為60秒
??session.setMaxInactiveInterval(60);。
上面的只是一個(gè)簡(jiǎn)單的模擬程序,存在許多缺陷。
總結(jié)
以上是生活随笔為你收集整理的利用Servlet监听器实现简单网站访问量和在线人数统计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 密钥生成器KeyPairGenerato
- 下一篇: 一次索引搞定的调优例子