文章目录
- 监听器使用
- 监听器类型
- ServletContextListener
- HttpSessionListener
- ServletRequestListener
- ServletContextAttributeListener
- HttpSessionAttributeListener
- ServletRequestAttributeListener
- HttpSessionBindingListener
监听器(Listener)组件用于监听特定事件的发生,并在事件触发时执行相应的处理逻辑。监听器主要基于Java的观察者模式实现,可以用来监控应用程序的生命周期事件,如请求、会话和属性的变化等。
监听器使用
监听器通常在 web.xml
配置文件中进行注册,也可以使用注解的方式。
<listener>
<listener-class>com.example.MyContextListener</listener-class>
</listener>
使用注解配置(需要Servlet 3.0及以上)
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// 应用启动时执行的代码
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// 应用关闭时执行的代码
}
}
监听器类型
监听三个域对象的创建和销毁事件的监听器:ServletContextListener
、HttpSessionListener
和 ServletRequestListener
监听域对象中属性的增加、删除、替换事件的监听器:ServletContextAttributeListener
、HttpSessionAttributeListener
和 ServletRequestAttributeListener
监听绑定到 HttpSession
域中的某个对象的状态的监听器,又称为感知型监听器:HttpSessionBindingListener
ServletContextListener
用于监听ServletContext的创建和销毁事件。当Web应用启动或关闭时,可以执行初始化和清理工作。
public interface ServletContextListener extends EventListener {
// 当Web应用启动时调用
void contextInitialized(ServletContextEvent sce);
// 当Web应用关闭时调用
void contextDestroyed(ServletContextEvent sce);
}
HttpSessionListener
用于监听HTTP会话的创建和销毁事件。可以在用户登录或注销时进行相应的处理,比如记录在线用户数量。
public interface HttpSessionListener extends EventListener {
// 当一个新的HttpSession被创建时调用
void sessionCreated(HttpSessionEvent se);
// 当一个HttpSession被销毁时调用
void sessionDestroyed(HttpSessionEvent se);
}
ServletRequestListener
用于监听Servlet请求的创建和销毁事件。可以在请求处理的开始和结束时执行一些操作,比如记录日志。
public interface ServletRequestListener extends EventListener {
// 当一个请求被初始化时调用
void requestInitialized(ServletRequestEvent sre);
// 当一个请求结束时调用
void requestDestroyed(ServletRequestEvent sre);
}
ServletContextAttributeListener
用于监听ServletContext属性的添加、移除和替换。
public interface ServletContextAttributeListener extends EventListener {
// 当一个属性被添加到ServletContext时调用
void attributeAdded(ServletContextAttributeEvent scae);
// 当一个属性从ServletContext中移除时调用
void attributeRemoved(ServletContextAttributeEvent scae);
//当一个属性在ServletContext中被替换时调用
void attributeReplaced(ServletContextAttributeEvent scae);
}
HttpSessionAttributeListener
用于监听会话属性的添加、修改和移除事件。适合在会话中添加或删除属性时进行处理。
public interface HttpSessionAttributeListener extends EventListener {
// 当一个属性被添加到HttpSession时调用
void attributeAdded(HttpSessionBindingEvent se);
// 当一个属性从HttpSession中移除时调用
void attributeRemoved(HttpSessionBindingEvent se);
// 当一个属性在HttpSession中被替换时调用
void attributeReplaced(HttpSessionBindingEvent se)
}
ServletRequestAttributeListener
用于监听请求属性的变化,适合监控请求数据的添加或修改。
public interface ServletRequestAttributeListener extends EventListener {
// 当一个属性被添加到ServletRequest时调用
void attributeAdded(ServletRequestAttributeEvent srae);
// 当一个属性从ServletRequest中移除时调用
void attributeRemoved(ServletRequestAttributeEvent srae);
// 当一个属性在ServletRequest中被替换时调用
void attributeReplaced(ServletRequestAttributeEvent srae);
}
使用监听器统计在线人数
HttpSessionBindingListener
接口定义
public interface HttpSessionBindingListener extends EventListener {
void valueBound(HttpSessionBindingEvent event);
void valueUnbound(HttpSessionBindingEvent event);
}
创建一个类实现 HttpSessionBindingListener
接口。valueBound
和 valueUnbound
方法分别在对象绑定到会话和从会话中解除绑定时调用
public class OnlineUserCounter implements HttpSessionBindingListener {
private static int onlineCount = 0;
@Override
public void valueBound(HttpSessionBindingEvent event) {
// 用户登录时增加在线用户数
synchronized (OnlineUserCounter.class) {
onlineCount++;
}
System.out.println("用户登录,当前在线人数: " + onlineCount);
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
// 用户登出或会话过期时减少在线用户数
synchronized (OnlineUserCounter.class) {
if (onlineCount > 0) {
onlineCount--;
}
}
System.out.println("用户登出,当前在线人数: " + onlineCount);
}
public static int getOnlineCount() {
return onlineCount;
}
}
创建一个Servlet类来处理登录请求,并在登录成功时将 OnlineUserCounter
实例添加到会话中
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
// 假设验证逻辑
if ("admin".equals(username) && "123456".equals(password)) {
HttpSession session = request.getSession();
OnlineUserCounter counter = new OnlineUserCounter();
session.setAttribute("user", username); // 设置用户名
session.setAttribute("counter", counter); // 绑定计数器
// 重定向到欢迎页面
response.sendRedirect("welcome.jsp");
} else {
// 重定向到登录页面,并携带错误信息
response.sendRedirect("login.jsp?error=true");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
创建一个Servlet类来处理登出请求,并使会话失效
public class LogoutServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate(); // 使会话失效
}
response.sendRedirect("login.jsp");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
在 web.xml
文件中配置 LoginServlet
、LogoutServlet
以及在线用户统计监听器
<!-- 配置LoginServlet -->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.hz.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<!-- 配置LogoutServlet -->
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.hz.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
创建登录页面
<div align="center">
<form action="login" method="post">
<table>
<tr>
<td>账号 : </td>
<td><input type="text" name="username" required></td>
</tr>
<tr>
<td>密码 : </td>
<td><input type="password" name="password" required></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="登录">
</td>
</tr>
</table>
</form>
</div>
创建欢迎页面,显示当前在线用户数
<h1>欢迎您, <%= session.getAttribute("user") %>!</h1>
<p>当前在线人数: <%= com.hz.OnlineUserCounter.getOnlineCount() %></p>
<form action="logout" method="post">
<input type="submit" value="退出">
</form>
HttpSessionListener
<!-- 配置在线用户统计监听器 -->
<listener>
<listener-class>com.hz.OnlineUserCounter</listener-class>
</listener>
两者对比
HttpSessionListener
用于会话生命周期管理(用于监听会话的创建和销毁事件)和全局监听(设置一次即可监听整个应用中的所有会话)。
当一个新的会话被创建时,sessionCreated
方法会被调用;当一个会话被销毁时(例如,调用 session.invalidate()
或会话超时),sessionDestroyed
方法会被调用。
- HttpSessionListener 用于监听会话的创建和销毁事件,适用于全局的会话管理。
- HttpSessionListener 只需要设置到web.xml就可以监听整个应用中的所有session
HttpSessionBindingListener
用于对象绑定和解绑事件(监听对象被绑定到会话或从会话中解绑的事件)和局部监听(必须实例化后放入某一个会话中,才能监听该会话中的对象绑定和解绑事件)。
当一个实现了 HttpSessionBindingListener
接口的对象被绑定到会话时,valueBound
方法会被调用;当一个实现了 HttpSessionBindingListener
接口的对象从会话中解绑时(例如,调用 session.removeAttribute()
或会话销毁),valueUnbound
方法会被调用。
- HttpSessionBindingListener 用于监听特定对象被绑定到会话或从会话中解绑的事件,适用于对象级别的生命周期管理。
- HttpSessionBindingListener 必须实例化后放入某一个session中,才能监听