监听器的使用

  1. 在线客户端统计统计的是访问的IP,通过IP去统计访问量,然后再安全退出。
  2. 首先在建立一个web工程
  3. 然后创建MyServletContextListener类去实现ServletContextListener接口,在web工程启动时创建对象,创建Map集合,然后把集合对象放到ServletContext域中
  4. 接着在com.bjpowernode.listeners包下建立MyRequestListener类去实现ServletRequestListener接口,它在浏览器向服务器发出请求时初始化创建请求对象,用sre.getServletRequest()方法去获取request,进而用getRemoteAddr()获取到IP,然后创建session域,再创建Map集合,从Map中获取由当前IP所发出的所有Session组成的List,判断当前的List是否为null.若为null,则创建List,遍历List.若List中存在当前Session对象,则不用操作List
  5. 执行安全退出操作,创建Session域,使Session失效,让MySessionListener类去实现 HttpSessionListener接口,然后安全退出,具体代码如下

MyServletContextListener类

package com.bjpowernode.listeners;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

public class MyServletContextListener implements ServletContextListener {
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		//创建一个Map,key为ip,value为该ip上所发出的会话对象
		Map<String,List<HttpSession>> map=new HashMap<>();
		//获取ServletContext,即全局域对象
		ServletContext sc = sce.getServletContext();
		//将map放入到全局域中
		sc.setAttribute("map", map);
	}
 
}

 MyRequestListener类

package com.bjpowernode.listeners;

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

import javax.servlet.ServletContext;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class MyRequestListener implements ServletRequestListener {
	//将当前Session对象存放到List中
	@Override
	public void requestInitialized(ServletRequestEvent sre) {
		// 获取当前request
		HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
		// 获取当前ip
		String clientIp = request.getRemoteAddr();
		// 获取当前session对象
		HttpSession currentsession = request.getSession();
		// 获取全局域
		ServletContext sc = sre.getServletContext();
		Map<String, List<HttpSession>> map = (Map<String, List<HttpSession>>) sc.getAttribute("map");
		//从Map中获取由当前IP所发出的所有Session组成的List
		List<HttpSession> sessions = map.get(clientIp);
		//判断当前的List是否为null.若为null,则创建List.
		if(sessions==null) {
			sessions=new ArrayList<>();
		}
		//遍历List.若List中存在当前Session对象,则不用操作List
		for (HttpSession httpSession : sessions) {
			if(httpSession==currentsession) {
				return;
			}
		}  
		//将当前Session放入到这个List
		sessions.add(currentsession);
		//将变化过的List重新写回到map
		map.put(clientIp, sessions);
		//将变化过的map重新写回到全局域
		sc.setAttribute("map", map);
		
		//将当前ip放入到当前session
		currentsession.setAttribute("clientIp",clientIp);
	}
}

 MySessionListener类

package com.bjpowernode.listeners;

import java.util.List;
import java.util.Map;

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

public class MySessionListener implements HttpSessionListener {
	//将当前Session对象从List中删除
	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		//获取当前Session对象
		HttpSession currentSession = se.getSession();
		//从当前Session中获取当前ip
	    String  clientIp = (String) currentSession.getAttribute("clientIp");
	    //获取全局域
		ServletContext sc = currentSession.getServletContext();
		//从全局域中获取map
		Map<String,List<HttpSession>> map=(Map<String, List<HttpSession>>) sc.getAttribute("map");
		//从Map中获取List
		List<HttpSession> sessions = map.get(clientIp);
		//从List中删除当前Session对象
		sessions.remove(currentSession);
		//若List中没有了元素,则说明当前IP所发出的会话全部关闭,那么就可以从map中将当前ip所对应的Entry对象删除
		//若List中仍有元素,则说明当前IP所发出的会话还存在,那么将这个变化过的List写回到map 
		if(sessions.size()==0) {
			map.remove(clientIp);
		}else {
			map.put(clientIp, sessions);
		}
		//将变化过的写回到全局域
		sc.setAttribute("map", map);
	}
	
}

LogoutServlet 类

package com.bjpowernode.servlets;

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 LogoutServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
			throws ServletException, IOException {
		HttpSession session = request.getSession(false);
		if(session!=null) {
			session.invalidate();
		}
	}

}

web.xml注册监听器和跳转到退出

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>12-clientCount</display-name>
  <listener>
    <listener-class>com.bjpowernode.listeners.MyRequestListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.bjpowernode.listeners.MyServletContextListener</listener-class>
  </listener>
  <listener>
    <listener-class>com.bjpowernode.listeners.MySessionListener</listener-class>
  </listener>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <description></description>
    <display-name>LogoutServlet</display-name>
    <servlet-name>LogoutServlet</servlet-name>
    <servlet-class>com.bjpowernode.servlets.LogoutServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>LogoutServlet</servlet-name>
    <url-pattern>/logoutServlet</url-pattern>
  </servlet-mapping>
</web-app>

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%> 
	<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	您是第${map.size()}位访客。<br>
	安全<a href="${pageContext.request.contextPath }/logoutServlet">退出</a>
	
	<br>
	
	<c:forEach items="${map }" var="entry">
	${entry.key}=${entry.value.size()}<br>
	</c:forEach>
</body>
</html>