最近在學習Javaweb相關的內容(不黑不吹之前對web開發零基礎),下面通過一個統計在線人數的小栗子講講Servlet監聽器吧
開發環境 eclipse tomcat 7
先說說這個小栗子的構思:
首先要考慮的就是通過什么方式能夠統計在線人數?很容易想到可以通過session來統計在線人數為什么不是request呢?因為request在請求結束時即服務器返回資源時就被銷毀了,也就是說request的作用域不足以用以統計在線人數。服務器在第一次接受一個用戶請求時會給該用戶分配一個sessionid在有效期結束后或是用戶主動關閉瀏覽器一段時間后session會被銷毀,所以用session來統計在線人數是合情合理的。
接下來問題來了,知道了統計在線人數和session相關那么應該如何操作呢?下面說說Servlet監聽器。
Servlet監聽器只要就是用來對Web應用進行監聽和控制的,功能接近Java的GUI程序的監聽器,可以監聽由於Web應用程序狀態改變而引起的Servlet容器產生的相應事件,然后作出處理。
Servlet監聽器分為Servlet上下文監聽器,Http會話監聽器,Servlet請求監聽器。
既然用到了Session那我們先來看看Session相關的監聽器吧。查看Apache文檔
HttpSessionListener接口有兩個方法對應的是session被創建和被銷毀時調用的。定義一個監聽器類實現HttpSessionListener接口代碼如下所示
1 package com.xiaoysec; 2 3 import java.util.ArrayList; 4 5 import javax.servlet.annotation.WebListener; 6 import javax.servlet.http.HttpSessionEvent; 7 import javax.servlet.http.HttpSessionListener; 8 9 /** 10 * Application Lifecycle Listener implementation class MyHttpSessionListener 11 * 12 */ 13 14 public class MyHttpSessionListener implements HttpSessionListener { 15 private int numberCount = 0; 16 17 /** 18 * Default constructor. 19 */ 20 public MyHttpSessionListener() { 21 // TODO Auto-generated constructor stub 22 } 23 24 /** 25 * @see HttpSessionListener#sessionCreated(HttpSessionEvent) 26 */ 27 public void sessionCreated(HttpSessionEvent arg0) { 28 // TODO Auto-generated method stub 29 numberCount++; 30 arg0.getSession().getServletContext() 31 .setAttribute("numberCount", numberCount); 32 } 33 34 /** 35 * @see HttpSessionListener#sessionDestroyed(HttpSessionEvent) 36 */ 37 public void sessionDestroyed(HttpSessionEvent arg0) { 38 // TODO Auto-generated method stub 39 numberCount--; 40 arg0.getSession().getServletContext() 41 .setAttribute("numberCount", numberCount); 42 ArrayList<Userinfo> userlist = (ArrayList<Userinfo>) arg0.getSession() 43 .getServletContext().getAttribute("userlist"); 44 if (SessionUtil.getUsersessionid(userlist, arg0.getSession().getId()) != null) { 45 userlist.remove(SessionUtil.getUsersessionid(userlist, arg0 46 .getSession().getId())); 47 } 48 } 49 50 }
在Session被創建時numberCount++,在被銷毀時numberCount--。這樣,一個簡單的在線人數統計功能就實現了,接下來完善一下,如果想看到客戶端的ip信息又該怎么辦呢?首先還是思考如何獲取用戶信息,很容易想到可以通過request獲取客戶端的信息。
定義一個封裝用戶信息的Javabean,代碼如下:
1 package com.xiaoysec; 2 3 public class Userinfo { 4 private String sessionid; 5 private String ip; 6 private String recenttime; 7 8 public String getSessionid() { 9 return sessionid; 10 } 11 12 public void setSessionid(String sessionid) { 13 this.sessionid = sessionid; 14 } 15 16 public String getIp() { 17 return ip; 18 } 19 20 public void setIp(String ip) { 21 this.ip = ip; 22 } 23 24 public String getRecenttime() { 25 return recenttime; 26 } 27 28 public void setRecenttime(String recenttime) { 29 this.recenttime = recenttime; 30 } 31 32 }
定義一個類MyServletRquestListener實現ServletRequestListener接口,在該接口中定義了一個requestInitialized方法,在服務器端接收到客戶端的請求時被調用,
代碼如下:
1 package com.xiaoysec; 2 3 import java.text.SimpleDateFormat; 4 import java.util.ArrayList; 5 import java.util.Date; 6 7 import javax.servlet.ServletRequestEvent; 8 import javax.servlet.ServletRequestListener; 9 import javax.servlet.annotation.WebListener; 10 import javax.servlet.http.HttpServletRequest; 11 12 public class MyServletRquestListener implements ServletRequestListener { 13 private ArrayList<Userinfo> userlist; // 在綫用戶的list 14 15 @Override 16 public void requestDestroyed(ServletRequestEvent arg0) { 17 // TODO Auto-generated method stub 18 19 } 20 21 /** 22 * 在初始化request的初始化中判斷是否存在user的信息(sessionid)如果不存在的話就保存在userlist中 23 */ 24 @Override 25 public void requestInitialized(ServletRequestEvent arg0) { 26 userlist = (ArrayList<Userinfo>) arg0.getServletContext().getAttribute("userlist"); 27 if(userlist==null) 28 userlist = new ArrayList<Userinfo>(); 29 HttpServletRequest req = (HttpServletRequest) arg0.getServletRequest(); 30 String sessionid = req.getSession().getId(); 31 if (SessionUtil.getUsersessionid(userlist, sessionid) == null) { 32 Userinfo user = new Userinfo(); 33 user.setIp(req.getRemoteAddr()); 34 user.setSessionid(sessionid); 35 user.setRecenttime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") 36 .format(new Date())); 37 userlist.add(user); 38 } 39 arg0.getServletContext().setAttribute("userlist", userlist); 40 } 41 42 }
接着寫一個SessionUtil類實現了getUsersessionid方法,代碼如下:
1 package com.xiaoysec; 2 3 import java.util.ArrayList; 4 5 public class SessionUtil { 6 public static Object getUsersessionid(ArrayList<Userinfo> userlist,String sessionid) { 7 for(int i=0;i<userlist.size();i++){ 8 Userinfo info = userlist.get(i); 9 if(userlist.get(i).getSessionid().equals(sessionid)) //表示當前的sessionid用戶存在於用戶list中不需要 10 return info; 11 } 12 return null; 13 } 14 15 }
在getUsersessionid中參數為userlist和sessionid,通過一個循環判斷sessionid所指的用戶是否在userlist中如果在的話就返回用戶信息info,如果不在的話就返回null並在MyServletRquestListener的31行處添加進userlist。
最后是界面jsp展示
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@ page import="java.util.*"%> 4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 5 <html> 6 <head> 7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 8 <title>Insert title here</title> 9 </head> 10 <body> 11 當前用戶在線人數<%= application.getAttribute("numberCount") %><br/> 12 <% 13 ArrayList<com.xiaoysec.Userinfo> userlist = (ArrayList<com.xiaoysec.Userinfo>)request 14 .getServletContext().getAttribute("userlist"); 15 if(userlist!=null){ 16 for (int i=0;i<userlist.size();i++) { 17 com.xiaoysec.Userinfo info = userlist.get(i); 18 %> 19 ip:<%=info.getIp()%><br /> 20 recentTime:<%=info.getRecenttime()%><br/> 21 sessionid:<%=info.getSessionid()%><br/> 22 <% 23 }} 24 %> 25 </body> 26 </html>
總結:通過這個小栗子只是對Servlet監聽器有一個小小的了解,還是需要多看源碼,理解過程,多代碼,多思考,多總結。