1. 程式人生 > >Servlet監聽器——實現線上登入人數統計小例子

Servlet監聽器——實現線上登入人數統計小例子

一、概念

servlet監聽器的主要目的是給web應用增加事件處理機制,以便更好的監視和控制web應用的狀態變化,從而在後臺呼叫相應處理程式。

二、監聽器的型別

1.根據監聽物件的型別和範圍,分為3

Request事件監聽器

HttpSession事件監聽器

ServletContext事件監聽器

2.八個監聽介面和六個監聽事件


三、ServletContext監聽

1.Application物件

application是ServletContext的例項,由JSP容器預設建立。Servlet中呼叫getServletContext()方法得到ServletContext的例項。

全域性物件即Application範圍的物件,初始化階段的變數值在web.xml中,經由<context-param>元素所設定的變數,它的範圍也是Application的範圍

2.ServletContextListener介面

用於監聽Web應用啟動和銷燬的事件,監聽器類需要實現ServletContextListener介面。

該介面的主要方法;

void contextInitialized(ServletContextEvent se):通知正在接受的物件,應用程式已經被載入及初始化

void contextDestroyed(ServletContextEvent se):通知正在接受的物件,應用程式已經被銷燬

ServletContextEvent的主要方法:ServletContext getServletContext():取得當前的ServletContext物件

3.ServletContextAttributeListener

用於監聽Web應用屬性改變的事件,包括增加、刪除、修改屬性。監聽器類需要實現ServletContextAttributeListener介面

ServletContextAttributeListener介面的主要方法:

void attributeAdded(ServletContextAttributeEvent se):若有物件加入Application的範圍,通知正在收聽的物件。

void attributeRemoved(ServletContextAttributeEvent se):若有物件從Application範圍移除,通知正在收聽的物件。

void attributeReplaced(ServletContextAttributeEvent se):若在Application的範圍中,有物件取代另一個物件時,通知正在收聽的物件

ServletContextAttributeEvent中的主要方法:

getName():返回屬性名稱

getValue()返回屬性的值

四、HttpSession 會話監聽

1.HttpSessionListener

主要方法:

sessionCreated(HttpSessionEvent se):session建立

sessionDestroyed(HttpSessionEvent se):session銷燬

2.HttpSessionActivationListener:

監聽器監聽Http會話的情況

3.HttpSessionAttributeListener:

監聽HttpSession中屬性的操作

該介面的主要方法:

void attributeAdded(HttpSessionBindingEvent se):監聽Http會話中的屬性新增

void attributeRemoved(HttpSessionBindingEvent se):監聽Http會話中的屬性移除

void attributeReplaced(HttpSessionBindingEvent se):監聽Http會話中的屬性更改操作

4.HttpSessionBindingListener

監聽Http會話中物件的繫結資訊

getSession():獲取session物件

getName():返回session增加、刪除、或替換的屬性名稱

getValue():返回session增加、刪除、或替換的屬性值

五、ServletRequest監聽

可以監聽客戶端的請求

1.ServletRequestListener介面

用於監聽客戶端的請求初始化和銷燬事件,需要實現ServletRequestListener介面 介面中的方法: requestInitialized(ServletRequestEvent):通知當前物件請求已經被載入及初始化 requestDestroyed(ServletRequestEvent):通知當前物件,請求已經被消除 ServletRequestEvent例項中的方法 getServletRequest():獲取ServletRequest物件 getServletContext():獲取ServletContext物件 2.ServletRequestAttributeListener 用於監聽Web應用屬性改變的事件,包括增加屬性、刪除屬性、修改屬性 介面方法: void attributeAdded(ServletRequestAttributeEvent e):向Request物件新增新屬性 void attributeRemoved(ServletRequestAttributeEvent e):從request物件中刪除屬性 void attributeReplaced(ServletRequestAttributeEvent e):替換物件中現有屬性值 ServletRequestAttributeEvent中的主要方法:
getName():返回Request增加、刪除、或替換的屬性名稱 getValue():返回Request增加、刪除、或替換的屬性的值

六、儲存線上使用者資訊的例子

1.login.jsp頁面實現使用者登入

<body>
	<form method="get" action="logindo">
		<center>
			<h2>使用者登入</h2>
			<hr />
			<br /> 使用者名稱: <input type="text" name="userName" /> <br /> 
			<input type="submit" value="登入" />
		</center>
	</form>
</body>

2.建立儲存使用者資訊的類:UserList.java

package listener;

import java.util.Vector;

public class UserList {
	private static Vector online = new Vector();
	//新增線上人數
	public static void addUser(String userName){
		online.addElement(userName);
	}
	//移除線上人數
	public static void removeUser(String userName){
		online.removeElement(userName);
	}
	//獲取線上使用者數量
	public static int getUserCount(){
		return online.size();
	}
	public static Vector getVector(){
		return online;
	}
}

****Vector 類提供了實現可增長陣列的功能,隨著更多元素加入其中,陣列變的更大。在刪除一些元素之後,陣列變小。 

Vector 有三個建構函式, 
public Vector(int initialCapacity,int capacityIncrement)  

public Vector(int initialCapacity)

public Vector()   

Vector 執行時建立一個初始的儲存容量initialCapacity,儲存容量是以capacityIncrement 變數定義的增量增長。初始的儲存容量和capacityIncrement 可以在Vector 的建構函式中定義。第二個建構函式只建立初始儲存容量。第三個建構函式既不指定初始的儲存容量也不指定capacityIncrement。   

Vector 類提供的訪問方法支援類似陣列運算和與Vector 大小相關的運算。類似陣列的運算允許向量中增加,刪除和插入元素。

****

3.寫監聽器類

package listener;

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class OnlineListener implements HttpSessionListener,HttpSessionAttributeListener{
	//監聽Http會話中的屬性新增
	public void attributeAdded(HttpSessionBindingEvent se) {
		// TODO Auto-generated method stub
		UserList.addUser(String.valueOf(se.getValue()));//增加一個使用者
		System.out.println("session("+se.getSession().getId()+")增加屬性"+se.getName()+",值為"+se.getValue());
	}
	//監聽Http會話中的屬性移除
	public void attributeRemoved(HttpSessionBindingEvent se) {
		// TODO Auto-generated method stub
		UserList.removeUser(String.valueOf(se.getValue()));
		System.out.println(se.getValue()+"屬性已移除");
	}
	//監聽Http會話中的屬性更改操作
	public void attributeReplaced(HttpSessionBindingEvent se) {
		// TODO Auto-generated method stub
		String oldValue=String.valueOf(se.getValue());//舊的屬性
		String newValue=String.valueOf(se.getSession().getAttribute(se.getName()));//新的屬性
		UserList.removeUser(oldValue);//移除舊的屬性
		UserList.addUser(newValue);//增加新的屬性
		System.out.println(oldValue+"屬性已更改為"+newValue);
	}

	public void sessionCreated(HttpSessionEvent se) {
		// TODO Auto-generated method stub
		System.out.println("會話已建立!");
	}

	public void sessionDestroyed(HttpSessionEvent se) {
		// TODO Auto-generated method stub
		System.out.println("會話已銷燬!");
	}

}

4.建立使用者登入類LoginServlet.java

package listener;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class LoginServlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		String userName=req.getParameter("userName");//獲取前臺傳來的userName屬性
		HttpSession session = req.getSession();
		session.setAttribute("userName", userName);//將屬性儲存到session會話中
		resp.sendRedirect("index.jsp");//重定向到index.jsp頁面
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(req, resp);
	}
}

5.建立退出登入類

package listener;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class ExitServlet extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		req.getSession().removeAttribute("userName");//從session中移除物件
		resp.sendRedirect("login.jsp");//重定向到使用者登入頁面
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(req, resp);
	}
}

6.在web.xml中配置監聽器、登入和退出的Servlet

  <!-- 配置監聽器 -->
  <listener>
  	<listener-class>listener.OnlineListener</listener-class>
  </listener>	
  <!-- 配置servlet -->
  <servlet>
  	<servlet-name>LoginServlet</servlet-name>
  	<servlet-class>listener.LoginServlet</servlet-class>
  </servlet>
  <servlet>
  	<servlet-name>ExitServlet</servlet-name>
  	<servlet-class>listener.ExitServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>LoginServlet</servlet-name>
  	<url-pattern>/logindo</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
  	<servlet-name>ExitServlet</servlet-name>
  	<url-pattern>/exitdo</url-pattern>
  </servlet-mapping>

7.編寫index.jsp線上首頁

<body>
	<%
		//如果未登入,轉向登入頁面
		if (session.getAttribute("userName") == null) {
			response.sendRedirect("login.jsp");
		}
		Vector onlineUsers = UserList.getVector(); //獲取儲存線上使用者名稱的vector物件
	%>
	<center>
		<br />
		<br />
		<h2>登入成功</h2>
		<hr />
		<br /> 歡迎你 <span style="color:red;"> <%=session.getAttribute("userName")%>
		</span>      <a href="exitdo">退出登入</a> <br />
		<br /> 當前線上人數:<span style="color:red;"> <%=UserList.getUserCount()%>人</span>
		<br />
		<br> 線上使用者名稱單 : <br /> <select multiple="multiple" name="list"
			style="width:200px;height:250px">
			<%
				for (int i = 0; i < onlineUsers.size(); i++) {
					out.write("<option>" + onlineUsers.get(i) + "</option>");
				}
			%>
		</select>
	</center>
</body>