分析

  操作ServletContextListener,ServletRequestListener,HttpSessionListener三个监听器
  Map里放session List,然后对Map进行操作,客户端ip为KEY,
  具体流程看代码注解。

实现

手机端

电脑端

代码

监听ServletContext的创建

package onlineUser;

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;

/**
 * 监听ServletContext的创建
 *
 */
public class MyServletContextListener implements ServletContextListener {

	/**
	 * ServletContext创建时初始化一个Map
	 */ 
    public void contextInitialized(ServletContextEvent sce)  { 
    	Map<String,List<HttpSession>> ipMap=new HashMap();
    	ServletContext servletContext=sce.getServletContext();
    	servletContext.setAttribute("ipMap", ipMap );  //将创建好的Map放到ServletContext域中
    	
    }
	
}

监听Request的对象

package onlineUser;

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;

/**
 * 监听Request的对象
 *
 */
public class MyRequestListener implements ServletRequestListener {


    public void requestInitialized(ServletRequestEvent sre)  { 
 //获取Request的对象  		
    	HttpServletRequest servletRequest=(HttpServletRequest)sre.getServletRequest();
 //得到客户端的IP
    	String ip=servletRequest.getRemoteAddr();
//获取ServletContext对象
    	ServletContext servletContext=sre.getServletContext();
    	Map<String,List<HttpSession>> ipMap=(Map<String,List<HttpSession>>)servletContext.getAttribute("ipMap");
//将SetRequest得到的IP做为key去Map中获取Value
    	List<HttpSession> list=ipMap.get(ip);  	
    	if (list ==null) {
//如果list为空,说明用户是第一次访问
    		list=new ArrayList<>();
    	}
// 获取当前Session   	
    	HttpSession currentSession=servletRequest.getSession();
//如果list是当前Session的话,说明是同一个会话请求,不需要处理
    	for(HttpSession s:list) {
    		if(s==currentSession) {
    			return;
    		}
    	}
 //如果以上条件都不满足的话,就说明这是一个新的Session对象,需要加入到list中
    	list.add(currentSession);
// 将list加入到Map中 
    	ipMap.put(ip, list);
    	
    	//因为session销毁时,需要ip地址,所以将ip放到session域中
    	currentSession.setAttribute("ip", ip);
    }
	
}

监听Session的销毁

package onlineUser;

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;

/**
 *监听Session的销毁
 *
 */
public class MySessionListener implements HttpSessionListener {

   
	/**
     * 当session销毁时,将session从对应的list中删除
     * 判断list是否为空,如果list为空,则说明ip已经离线,从Map中移除
     */
    public void sessionDestroyed(HttpSessionEvent se)  { 
//    	得到session对象
    	HttpSession currentSession=se.getSession();
    	//获取ServletContext对象
    	ServletContext servletContext=currentSession.getServletContext();
    	//从servletContext域中获取map
    	Map<String,List<HttpSession>> ipMap=(Map<String,List<HttpSession>>)servletContext.getAttribute("ipMap");
    	//从session中获取之前存放的ip地址
    	String ip=(String)currentSession.getAttribute("ip");
    	//根据ip在map中找相应的list
    	List<HttpSession> list=ipMap.get(ip);  	
    	//将待销毁的list从map中移除
    	list.remove(currentSession);
    	//如果list的长度为零的话,说明该ip所在的session全部失效(用户已离线),将ip从map中移除
    	//如果list的长度不为零的话,说明该ip所在的session还存在,将变化写到map中
    	if(list.size()==0) {
    		list.remove(ip);
    	}else {
    		ipMap.put(ip, list);
    	}
    	//将更新后的ipMap放到ServletContext域中
    	servletContext.setAttribute("ipMap",ipMap);
    	
    }
	
}

session销毁.安全退出

package onlineUser;

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 logoutServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
 
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	//将session销毁
		request.getSession().invalidate();
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		doGet(request, response);
	}

}

web.XML servlet配置

<?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>onlineUser</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <listener>
    <listener-class>onlineUser.MyServletContextListener</listener-class>
  </listener>
  <listener>
    <listener-class>onlineUser.MyRequestListener</listener-class>
  </listener>
  <listener>
    <listener-class>onlineUser.MySessionListener</listener-class>
  </listener>
  <servlet>
    <description></description>
    <display-name>logoutServlet</display-name>
    <servlet-name>logoutServlet</servlet-name>
    <servlet-class>onlineUser.logoutServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>logoutServlet</servlet-name>
    <url-pattern>/logout</url-pattern>
  </servlet-mapping>
</web-app>

index.jsp前台展示网页

	<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>在线人数统计</title>
</head>
<body>
本网站目前共有在线人数${ipMap.size() }个<br>
<a href="${pageContext.request.contextPath }/logout">安全退出</a>
</body>
</html>