Java Servlet监听器案例怎么实操

wen java案例 22

Java Servlet监听器实操案例

我将通过一个完整的在线用户统计案例,演示三种常用监听器的实操方法。

Java Servlet监听器案例怎么实操

项目结构

webapp/
├── WEB-INF/
│   └── web.xml
├── index.jsp
└── login.jsp

创建监听器类

1 统计在线用户 - ServletContextListener

package com.example.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class OnlineUserListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("=== 应用启动 ===");
        // 初始化在线用户计数器
        sce.getServletContext().setAttribute("onlineCount", 0);
        sce.getServletContext().setAttribute("userList", new java.util.ArrayList<String>());
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("=== 应用关闭 ===");
        // 清理资源
        sce.getServletContext().removeAttribute("onlineCount");
        sce.getServletContext().removeAttribute("userList");
    }
}

2 监听Session创建/销毁 - HttpSessionListener

package com.example.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class SessionTrackerListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("创建Session: " + se.getSession().getId());
        // 更新在线用户数
        javax.servlet.http.HttpSession session = se.getSession();
        javax.servlet.ServletContext context = session.getServletContext();
        synchronized (this) {
            Integer count = (Integer) context.getAttribute("onlineCount");
            context.setAttribute("onlineCount", (count == null ? 0 : count) + 1);
        }
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("销毁Session: " + se.getSession().getId());
        // 移除用户并更新计数
        javax.servlet.http.HttpSession session = se.getSession();
        javax.servlet.ServletContext context = session.getServletContext();
        synchronized (this) {
            // 移除用户
            java.util.ArrayList<String> userList = 
                (java.util.ArrayList<String>) context.getAttribute("userList");
            String username = (String) session.getAttribute("username");
            if (username != null && userList != null) {
                userList.remove(username);
            }
            // 更新计数
            Integer count = (Integer) context.getAttribute("onlineCount");
            context.setAttribute("onlineCount", (count == null ? 0 : count) - 1);
        }
    }
}

3 监听属性变化 - ServletRequestAttributeListener

package com.example.listener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class RequestLoggerListener implements ServletRequestAttributeListener {
    @Override
    public void attributeAdded(ServletRequestAttributeEvent srae) {
        System.out.println("添加属性: " + srae.getName() + 
                         " = " + srae.getValue());
    }
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        System.out.println("移除属性: " + srae.getName() + 
                         " = " + srae.getValue());
    }
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent srae) {
        System.out.println("替换属性: " + srae.getName() + 
                         " 旧值: " + srae.getValue() + 
                         " 新值: " + srae.getServletRequest().getAttribute(srae.getName()));
    }
}

创建测试用Servlet

package com.example.servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
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 action = req.getParameter("action");
        if ("login".equals(action)) {
            // 模拟登录
            req.getSession().setAttribute("username", username);
            // 添加到在线用户列表
            java.util.ArrayList<String> userList = 
                (java.util.ArrayList<String>) getServletContext().getAttribute("userList");
            if (userList != null && !userList.contains(username)) {
                userList.add(username);
            }
            resp.sendRedirect("index.jsp");
        } else if ("logout".equals(action)) {
            // 模拟登出
            req.getSession().invalidate();
            resp.sendRedirect("login.jsp");
        }
    }
}

创建JSP页面

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>登录页面</title>
</head>
<body>
    <h2>登录</h2>
    <form action="login" method="post">
        <input type="hidden" name="action" value="login">
        用户名:<input type="text" name="username"><br>
        <input type="submit" value="登录">
    </form>
</body>
</html>

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.ArrayList" %>
<html>
<head>首页</title>
</head>
<body>
    <h2>欢迎, ${sessionScope.username}</h2>
    <p>当前在线用户数:${applicationScope.onlineCount}</p>
    <h3>在线用户列表:</h3>
    <ul>
        <%
            ArrayList<String> userList = 
                (ArrayList<String>) application.getAttribute("userList");
            if (userList != null) {
                for (String user : userList) {
        %>
            <li><%= user %></li>
        <%
                }
            }
        %>
    </ul>
    <form action="login" method="post">
        <input type="hidden" name="action" value="logout">
        <input type="submit" value="退出登录">
    </form>
</body>
</html>

web.xml配置(可选)

如果使用了@WebListener注解,可以省略web.xml配置,但也可以使用XML方式:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <display-name>Listener Demo</display-name>
    <!-- 注册监听器 -->
    <listener>
        <listener-class>com.example.listener.OnlineUserListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.example.listener.SessionTrackerListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.example.listener.RequestLoggerListener</listener-class>
    </listener>
    <!-- 配置servlet -->
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.example.servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
    </servlet-mapping>
</web-app>

运行测试

  1. 部署应用到Tomcat等Servlet容器
  2. 访问 http://localhost:8080/your-app/login.jsp
  3. 输入用户名登录
  4. 打开多个浏览器窗口登录不同用户
  5. 观察控制台输出
  6. 点击退出查看在线用户数变化

常用监听器类型总结

监听器类型 监听事件 适用场景
ServletContextListener 应用启动/关闭 初始化资源、加载配置
HttpSessionListener Session创建/销毁 在线用户统计
ServletRequestListener 请求开始/结束 请求日志记录
ServletContextAttributeListener 应用属性变化 监控全局配置变更
HttpSessionAttributeListener Session属性变化 用户登录/登出监控
ServletRequestAttributeListener 请求属性变化 请求处理调试

注意事项

  • 线程安全:监听器在多线程环境下运行,注意使用同步
  • 内存泄漏:避免在监听器中持有强引用导致内存泄漏
  • 性能影响:监听器应快速执行,避免阻塞操作
  • 使用注解:Servlet 3.0+ 推荐使用@WebListener注解简化配置

这个案例演示了如何通过监听器实时监控用户登录/登出行为,是实际项目中常见的应用场景。

抱歉,评论功能暂时关闭!