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>
运行测试
- 部署应用到Tomcat等Servlet容器
- 访问
http://localhost:8080/your-app/login.jsp - 输入用户名登录
- 打开多个浏览器窗口登录不同用户
- 观察控制台输出
- 点击退出查看在线用户数变化
常用监听器类型总结
| 监听器类型 | 监听事件 | 适用场景 |
|---|---|---|
| ServletContextListener | 应用启动/关闭 | 初始化资源、加载配置 |
| HttpSessionListener | Session创建/销毁 | 在线用户统计 |
| ServletRequestListener | 请求开始/结束 | 请求日志记录 |
| ServletContextAttributeListener | 应用属性变化 | 监控全局配置变更 |
| HttpSessionAttributeListener | Session属性变化 | 用户登录/登出监控 |
| ServletRequestAttributeListener | 请求属性变化 | 请求处理调试 |
注意事项
- 线程安全:监听器在多线程环境下运行,注意使用同步
- 内存泄漏:避免在监听器中持有强引用导致内存泄漏
- 性能影响:监听器应快速执行,避免阻塞操作
- 使用注解:Servlet 3.0+ 推荐使用@WebListener注解简化配置
这个案例演示了如何通过监听器实时监控用户登录/登出行为,是实际项目中常见的应用场景。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播