1. 程式人生 > >JavaWeb-Servlet技術的監聽器-解析與例項-網站線上使用者資訊與網頁點選量

JavaWeb-Servlet技術的監聽器-解析與例項-網站線上使用者資訊與網頁點選量

轉載請註明出處: http://blog.csdn.net/qq_26525215
本文源自

在Web專案中,我們對下面這幾個監聽器必須熟練的使用,它們的作用真的很大。熟練的使用後,可以使我們少繞彎路,少寫很多程式碼、

事件源             監聽對像的建立和銷燬           監聽對像上屬性的新增和刪除 
HttpSession       HttpSessionListener        HttpSessionAttributeListener - HttpSessionEvent

ServletRequest    ServletRequestListenr          ServletRequestAttributeListener - ServletRequestEvent

ServletContext   ServletContextListener      ServletContextAttributeListener - ServletContextEvent

監聽ServletContext的建立和銷燬:

開發步驟:
第一步:實現ServletContextListener介面。

implements ServletContextListener

第二步:實現兩個方法。
contextInitialized
contextDestroyed

ServletContext物件(專案)建立:
public void contextInitialized(ServletContextEvent sce) 

ServletContext物件(專案)消亡:
public void contextDestroyed(ServletContextEvent sce) 

第三步:在web.xml中新增<listener/>節點。
為什麼要配web.xml呢,因為我們的專案在啟動的時候就需要監聽,不可能由專案內部的類來完成,所以這個實現得依靠伺服器了(在這裡是Tomcat)

位置是在:filter- mapping標籤之後 | listener | servlet標籤之前

<listener>
    <listener-class>
       完整類名
    </listener-class>
</listener>

這一點與swing中的新增監聽有所區別。

第四步:測試
1、釋出專案啟動。
2、通過Tomcat管理控制檯停止此專案。(注意,不要通過myEclipse直接停Java虛擬機器了)

監聽ServletContext上的屬性變化:

實現ServletContextAttributeListener介面:

implements ServletContextAttributeListener

實現三個方法:

    新增屬性時自動呼叫
    public void attributeAdded(ServletContextAttributeEvent e) {    
    }

    刪除屬性時自動呼叫
    public void attributeRemoved(ServletContextAttributeEvent e) {  
    }

    修改屬性時自動呼叫
    public void attributeReplaced(ServletContextAttributeEvent e) { 
    }

配置web.xml:

<listener>
    <listener class>
        完整類名
    </listener-class>
</listener>

例如:在jsp頁面中:

<%
     application.setAttribute("aa", "abc");//呼叫新增或修改屬性時的方法
     application.removeAttribute("aa");//呼叫刪除屬性時的方法
%>

例項-網站線上人資訊與網頁點選量

分析:

網頁點選量:

記錄一個網站的點選量。
當伺服器關閉時,必須要儲存到檔案中或是資料庫中去。
當伺服器啟動時,先從檔案中讀取並放到ServletContext。
在Filter中(用ServletRequestListenr也可以)記錄訪問量,每次訪問都加1。

好處:資訊不是太重要,沒有必要每次使用者訪問都訪問資料庫或是操作檔案。

在為不影響使用者的速度感受,應該開始一個新的執行緒同去操作資料。
這樣即使在後臺使用同步技術,使用者也不會感覺到速度很慢。

線上人資訊:

利用HttpSessionListener,監聽HttpSession的建立和銷燬。
sessionCreated
sessionDestroyed

Session的預設有效時間為30分。可以通過配置的方式修改它的值。
可以呼叫session.invalidate方法銷燬當前Session.

主要作用是記錄當前所有線上人數,無論是使用者還是遊客。

HttpSessionAttributeListener
主要作用是:記錄當前在登入人數。注意,登入是指註冊成為合法使用者併成功登入的人。

原始碼:

index.jsp:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>線上人的資訊與網站點選量的實現</title>
  </head>

  <body>
    <h3>線上人的資訊與網站點選量的實現</h3>
    <a href='<c:url value="servlet/ShowServlet"></c:url>'>檢視線上人資訊</a>
    <hr/>
    <form action='<c:url value="servlet/LoginServlet"></c:url>' method="post">
         姓名:<input type="text" name="name" />
         <input type="submit" value="登入">
    </form>

    <br/>點選量:${count}
  </body>
</html>

MyServletRequestListenr

統計訪問量:

package cn.hncu.listeners;

import javax.servlet.ServletContext;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class MyServletRequestListenr implements ServletRequestListener{

    //有一個請求就會執行這裡
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        ServletContext sct = sre.getServletContext();
        new MyThread(sct).start();
    }

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
    }
}

class MyThread extends Thread{
    private ServletContext sct = null;
    private static Object obj = new Object();
    public MyThread(ServletContext sct) {
        this.sct=sct;
    }

    @Override
    public void run() {
        synchronized (obj) {
            sct.setAttribute("count", (Integer) sct.getAttribute("count") + 1);
        }
    }
}

MyServletContextListener

將訪問量資料持久化:

package cn.hncu.listeners;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener{

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //從伺服器硬碟把之前儲存的點選量資料讀取出來
        ServletContext sct = sce.getServletContext();
        String path = sct.getRealPath("/count.txt");

        try {
            BufferedReader br = new BufferedReader(new FileReader(path));
            String line = br.readLine();
            Integer count = Integer.valueOf(line);
            sct.setAttribute("count", count);
        } catch (Exception e) {
            //如果出異常了,我們認為檔案還不存在,伺服器第一次啟動
            e.printStackTrace();
            sct.setAttribute("count",new Integer(0));
        }

    }

    //關閉伺服器時
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //把當前servletContext容器中儲存的點選量資料 永久化到  伺服器硬碟
        ServletContext sct = sce.getServletContext();
        String path = sct.getRealPath("/count.txt");

        try {
            PrintWriter pw = new PrintWriter(path);
            pw.write(""+sct.getAttribute("count"));
            pw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }


    }

}

MyHttpSessionListener

統計線上人的資訊

package cn.hncu.listeners;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MyHttpSessionListener implements HttpSessionListener {

    //有 遊客/使用者 來訪問了
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        List<HttpSession> guests = (List<HttpSession>) se.getSession().getServletContext().getAttribute("guests");//線上人的集合
        if(guests==null){//第一個訪問網站的人--沙發
            guests = new ArrayList<HttpSession>();
            se.getSession().getServletContext().setAttribute("guests", guests);//設定guests屬性
        }
        guests.add(se.getSession());//將第一個使用者的session新增到線上人集合
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        List<HttpSession> guests = (List<HttpSession>) se.getSession().getServletContext().getAttribute("fuses");
        if(guests.contains(se.getSession())){
            guests.remove(se.getSession());
        }
    }
}

MyHttpSessionAttributeListener

統計線上使用者的資訊:

package cn.hncu.listeners;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

public class MyHttpSessionAttributeListener implements HttpSessionAttributeListener{

    //session新增屬性了,就會呼叫下面的attributeAdded方法
    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        if(se.getName().equals("name")){//代表添加了name屬性
            System.out.println("使用者"+se.getValue()+"登入了");
            List<HttpSession> logins = (List<HttpSession>) se.getSession().getServletContext().getAttribute("logins");

            if(logins==null){
                logins = new ArrayList<HttpSession>();
                se.getSession().getServletContext().setAttribute("logins", logins);
            }
            logins.add(se.getSession());
        }
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
    }

}

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name></display-name>

  <filter>
    <filter-name>charset</filter-name>
    <filter-class>cn.hncu.filter.CharsetFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>charset</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <listener>
    <listener-class>cn.hncu.listeners.MyServletContextListener</listener-class>
  </listener>
  <listener>
    <listener-class>cn.hncu.listeners.MyServletRequestListenr</listener-class>
  </listener>
  <listener>
    <listener-class>cn.hncu.listeners.MyHttpSessionAttributeListener</listener-class>
  </listener>
  <listener>
    <listener-class>cn.hncu.listeners.MyHttpSessionListener</listener-class>
  </listener>


  <servlet>
    <servlet-name>LoginServlet</servlet-name>
    <servlet-class>cn.hncu.servlets.LoginServlet</servlet-class>
  </servlet>
  <servlet>
    <servlet-name>ShowServlet</servlet-name>
    <servlet-class>cn.hncu.servlets.ShowServlet</servlet-class>
  </servlet>


  <servlet-mapping>
    <servlet-name>LoginServlet</servlet-name>
    <url-pattern>/servlet/LoginServlet</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>ShowServlet</servlet-name>
    <url-pattern>/servlet/ShowServlet</url-pattern>
  </servlet-mapping>



  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

演示結果:

完整原始碼連結:

myOnlinesWeb.zip檔案。

轉載請註明出處: http://blog.csdn.net/qq_26525215
本文源自