Listener
概述
监听器是 Servlet 中一种特殊的类,它们能帮助开发者监听 Web 中的特定事件,比如 ServletContext,HttpSession,ServletRequest 的创建和销毁;属性键值对的创建、销毁和修改等。可以在某些动作前后增加处理和操作。
作用
1、统计在线人数,利用 HttpSessionLisener 或 HttpSessionAttributeListener
2、加载初始化信息:利用 ServletContextListener
3、统计网站访问量
4、实现访问监控
常见 API【了解】
// 监听上下文对象的初始化和销毁
interface ServletContextListener
// 通知上下文对象正在被初始化
void contextInitialized(ServletContextEvent sce);
// 通知上下文对象即将被关闭
void contextDestroyed(ServletContextEvent sce);
// 监听上下文对象对属性的增删改操作
interface ServletContextAttributeListener
// 通知添加了属性
void attributeAdded(ServletContextAttributeEvent var1);
// 通知移除了属性
void attributeRemoved(ServletContextAttributeEvent var1);
// 通知修改了属性
void attributeReplaced(ServletContextAttributeEvent var1);
// 监听Session对象的创建和销毁
interface HttpSessionListener
// session已创建
void sessionCreated(HttpSessionEvent var1);
// session已销毁
void sessionDestroyed(HttpSessionEvent var1);
// 监听session的属性增删改操作
interface HttpSessionAttributeListener
// 通知session中添加了属性
void attributeAdded(HttpSessionBindingEvent var1);
// 通知session中移除了属性
void attributeRemoved(HttpSessionBindingEvent var1);
// 通知session中修改了属性
void attributeReplaced(HttpSessionBindingEvent var1);
// 监听请求的初始化和销毁
interface ServletRequestListener
// 通知请求对象被销毁
void requestDestroyed(ServletRequestEvent var1);
// 通知请求对象正在初始化
void requestInitialized(ServletRequestEvent var1);
// 监听请求的属性的增删改操作
interface ServletRequestAttributeListener
// 通知请求对象添加了属性
void attributeAdded(ServletRequestAttributeEvent var1);
// 通知请求对象移除了属性
void attributeRemoved(ServletRequestAttributeEvent var1);
// 通知请求对象修改了属性
void attributeReplaced(ServletRequestAttributeEvent var1);
两种配置方式
注解
步骤
1、实现监听器接口
2、重写抽象方法
3、声明@WebListener注解
案例代码
/**
* 通过注解配置监听器
*/
// 声明监听器注解
@WebListener
public class CreateListener implements ServletContextListener {
// 重写contextInitialized方法
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("Servlet be initialized!!");
}
// 重写contextDestroyed方法
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("Servlet be destroyed!!");
}
}
通过 web.xml 配置文件
监听器
/**
* 通过web.xml方式配置监听器
*/
public class XMLListener implements HttpSessionListener {
// 重写sessionCreated方法
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("Session be created: " + httpSessionEvent.getSession().getId());
}
// 重写sessionDestroyed方法
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("Session be destroyed!!");
}
}
Servlet
@WebServlet("/xml")
public class XMLServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession(true);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
web.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_3_1.xsd"
version="3.1">
<!--声明监听器所在的位置-->
<listener>
<listener-class>com.fc.listener.createByXml.XMLListener</listener-class>
</listener>
</web-app>
获取当前的在线人数【重点】
登录页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<form action="login" method="post">
<table align="center">
<tr>
<td>姓名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="reset" value="重置">
<input type="submit" value="提交">
</td>
</tr>
</table>
</form>
</body>
</html>
主页
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>主页</title>
</head>
<body>
<h1 align="right" style="color: deeppink"><a href="logout">退出登录</a></h1>
<h1 align="center" style="color: aqua">在线人数:${sessionCount}</h1>
</body>
</html>
登录业务逻辑
/**
* 登录操作,并且注册Session信息
*/
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置请求编码集
req.setCharacterEncoding("utf-8");
// 从前端获取参数
String username = req.getParameter("username");
String password = req.getParameter("password");
// 判断数据合法性
if ("张三".equals(username) && "123456".equals(password)) {
// 登录成功,创建session
HttpSession session = req.getSession(true);
// 设置过期时间
session.setMaxInactiveInterval(60 * 60);
// 设置登录到的用户名为参数
session.setAttribute("username", username);
// 创建Cookie并存入JSESSIONID
Cookie cookie = new Cookie("JSESSIONID", session.getId());
// 设置Cookie过期时间
cookie.setMaxAge(60 * 60);
// 通过响应对象将Cookie发送到浏览器
resp.addCookie(cookie);
// 重定向至主页
resp.sendRedirect("index.jsp");
} else {
// 登录失败,返回登录页重新登录
resp.sendRedirect("login.html");
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
退出登录业务逻辑
/**
* 退出登录,销毁Session
*/
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取当前已存在的session,注意要用false
HttpSession session = req.getSession(false);
// 判断session是否为空
if (session != null) {
// 移除对应键值对
session.removeAttribute("username");
// 销毁session
session.invalidate();
}
// 通过 JSESSIONID 获取 cookie 对象
Cookie cookie = new Cookie("JSESSIONID", "");
// 设置 cookie 的有效期为 0
cookie.setMaxAge(0);
// 发送Cookie数据至浏览器
resp.addCookie(cookie);
resp.sendRedirect("index.jsp");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
【注意】这里需要把 Session 中的属性键值对进行移除,否则监听器中无法获取对应信息
监听器
// 声明监听器注解
@WebListener
public class OnlineListener implements HttpSessionAttributeListener {
// 当前session的数量
private static int count = 0;
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
// 当session中添加了属性键值对时,说明有人登录成功,当前在线人数+1
count++;
// 将当前session的总数存入上下文对象中
httpSessionBindingEvent.getSession().getServletContext().setAttribute("sessionCount", count);
}
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
// 当退出登录时说明当前在线人数-1,session的数量-1
count--;
// 将当前session的总数存入上下文对象中
httpSessionBindingEvent.getSession().getServletContext().setAttribute("sessionCount", count);
}
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
}
}
【注意】如果使用 HttpSessionListener 会造成人未登录但在线人数却增加的 bug
版权属于:不冷
本文链接:https://www.buleng.xyz/archives/110/
转载时须注明出处及本声明