前言
要完成在线用户统计功能的监听器,需要实现如下3个接口。
- ServletContextListener接口
- 使用此接口的作用是:在应用初始化的时候向application中添加一个空的Set集合用来保存在线用户。
- HttpSessionAttributeListener接口
- 使用此接口的作用是:当用户登陆成功后,会向session中添加一个属性用来保存用户信息,这样就表示新用户登陆,之后把用户保存在在线用户列表中。
- HttpSessionListener接口
- 使用此接口的作用是:当用户注销后将用户信息从用户列表中删除。
关键代码
contextInitialized
public void contextInitialized(ServletContextEvent se) {
	//创建set,保存用户信息
	Set<Users> onLineUsers=new HashSet<Users>();
	application=se.getServletContext();
	application.setAttribute("onLineUsers", onLineUsers);
}
attributeAdded
	public void attributeAdded(HttpSessionBindingEvent se) {
		HttpSession session=se.getSession();
		//得到新用户
		Users user=(Users) session.getAttribute("user");
		//从application中取出在线用户列表
		Set<Users>  onLineUsers=(Set<Users>) application.getAttribute("onLineUsers");
		//把新用户放到集合中
		onLineUsers.add(user);				
	}
attributeRemoved
public void attributeRemoved(HttpSessionBindingEvent se) {
	//得到用户的注销信息
	Users logOutUser=(Users) se.getValue();
	//取出在线用户列表
	Set<Users>  onLineUsers=(Set<Users>) 							application.getAttribute("onLineUsers");
	onLineUsers.remove(logOutUser);
		
	}
sessionDestroyed
public void sessionDestroyed(HttpSessionEvent se) {
	//得到注销用户的session信息
	HttpSession session=se.getSession();
	//得到新用户的信息
	Users logOutUser=(Users) session.getAttribute("user");
	Set<Users>  onLineUsers=(Set<Users>) 							application.getAttribute("onLineUsers");
	onLineUsers.remove(logOutUser);
	}
案例实现
第一步:创建一个JavaWeb项目,配置pom.xml和web.xml
pom.xml
  <dependencies>
    <!--junit单元测试-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <!--jdbc连接mysql数据库-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.21</version>
    </dependency>
    <!--servlet-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <!--lombok-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
      <scope>provided</scope>
    </dependency>
    <!--jstl-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>litener</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.3.2</version>
      </plugin>
      <plugin>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>9.3.14.v20161028</version>
      </plugin>
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>2.1</version>
        <configuration>
          <port>8080</port>
          <path>/</path>
          <uriEncoding>UTF-8</uriEncoding>
          <server>tomcat7</server>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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"
         version="3.0">
  <display-name>Archetype Created Web Application</display-name>
</web-app>
第二步:创建展示和处理数据的JSP页面
onLineUsers.jsp
<%--
  Created by IntelliJ IDEA.
  User: 21038
  Date: 2024/9/19
  Time: 14:24
  To change this template use File | Settings | File Templates.
--%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<c:forEach items="${onLineUsers}" var="u">
  <li>${u}</li>
</c:forEach>
</ul>
</body>
</html>
第三步:创建对应的Servlet类
LoginServlet
package servlet;
import dao.UserDao;
import dao.impl.UserDaoImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        UserDao userDao =new UserDaoImpl();
        HttpSession session =req.getSession();
        int i = userDao.selectUserByuserNameAndpassword(username, password);
        if (i==1){
            session.setAttribute("username",username);
            req.getRequestDispatcher("userPage").forward(req,resp);
        }else {
            req.getRequestDispatcher("/login.jsp").forward(req,resp);
        }
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }
}
登录页面Login.jsp
<%--
  Created by IntelliJ IDEA.
  User: 21038
  Date: 2024/9/19
  Time: 10:17
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="login" method="post">
    管理员用户名:<input type="text" name="username"><br>
    管理员密码: <input type="text" name="password"><br>
    <input type="submit" value="登录"><br>
</form>
</body>
</html>
这里演示的这些代码段都是对应连接了数据库的操作,这里展示只是为了演示统计在线用户功能的实现思路,完整代码我会在servlet-crud案例中提供 。
第四步:监听session中的用户,书写监听器类
OnLineUserListener
package listener;
import entity.User;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.*;
import java.util.ArrayList;
import java.util.List;
@WebListener
public class OnLineUserListener implements ServletContextListener, HttpSessionListener, HttpSessionAttributeListener {
    ServletContext application;
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        List<String> onLineUsers =new ArrayList<>();
        application = servletContextEvent.getServletContext();
        application.setAttribute("onLineUsers",onLineUsers);
    }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    }
    @Override
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        HttpSession session =httpSessionBindingEvent.getSession();
        String username =(String) session.getAttribute("username");
        List<String> onLineUsers=(List<String>) application.getAttribute("onLineUsers");
        onLineUsers.add(username);
    }
    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
    }
    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
    }
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        HttpSession session= httpSessionEvent.getSession();
        String username= (String) session.getAttribute("username");
        List<String> onLineUsers= (List<String>) application.getAttribute("onLineUsers");
        onLineUsers.remove(username);
    }
}
演示效果
登录页面

登录成功页面:

查看在线用户数

此时只有root用户在线
关键点:
- 创建登录页面
- 创建对应的servlet将登录用户信息存在session中
- 创建监听器,监听在线用户
- 创建在线统计页面,展示监听的在线用户信息



















