【Java web】过滤器与监听器详解
摘要: 本文通过书店类比,介绍了JavaWeb中的过滤器(Filter)和监听器(Listener)。过滤器像“安检员”,拦截请求/响应,实现登录验证、编码统一等功能;监听器像“监控摄像头”,监听应用事件(如会话创建/销毁),用于统计在线人数等场景。文章对比了两者的使用场景(过滤器主动拦截请求,监听器被动响应事件),并提供了登录验证过滤器和在线人数监听器的代码示例。最后强调关键注意事项:过滤器需调
一、什么是过滤器和监听器?—— 生活中的类比
想象你经营着一家在线书店(没错,还是我们的老例子!),为了保证书店正常运营,你需要两种关键角色:
- 过滤器(Filter):像书店门口的 保安,所有顾客(请求)进入前必须经过检查 —— 没带口罩?禁止入内!带了危险品?拦下!只有符合条件的人才能进店。
- 监听器(Listener):像书店里的 监控系统,默默记录顾客进出(会话创建 / 销毁)、货架商品变动(属性变更)等事件,一旦发生异常就会触发警报。
在 Java Web 中,过滤器负责拦截请求 / 响应,监听器负责监听 Web 应用事件,两者配合让 Web 应用更安全、可控。
二、过滤器(Filter)—— 请求的 “安检员”
1. 核心概念:过滤器能做什么?
过滤器就像 “请求安检员”,在请求到达 Servlet 之前、响应返回客户端之前 “拦截” 并处理:
- 登录验证:未登录用户禁止访问订单页面
- 统一编码:把所有请求的编码设为 UTF-8,避免乱码
- 敏感词过滤:把评论中的 “垃圾话” 替换成 ***
- 日志记录:记录谁访问了哪个页面、什么时间访问
2. 过滤器的 “一生”:生命周期
过滤器的工作流程就像保安的一天:
| 阶段 | 方法 | 类比场景 | 特点 |
|---|---|---|---|
| 初始化 | init(FilterConfig) |
保安上班,领取装备(配置) | 服务器启动时执行,仅 1 次 |
| 工作中 | doFilter(...) |
检查每个进出的人(请求) | 每次请求都执行 |
| 下班 | destroy() |
保安下班,归还装备 | 服务器关闭时执行,仅 1 次 |
3. 动手写一个登录验证过滤器
假设我们的在线书店需要验证用户是否登录才能访问 /order 页面,过滤器代码如下:
// 登录验证过滤器
@WebFilter("/order/*") // 拦截所有以/order开头的请求
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
// 1. 转换为HTTP请求/响应(获取会话)
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// 2. 检查Session中是否有登录用户
HttpSession session = request.getSession();
if (session.getAttribute("loginUser") == null) {
// 未登录,重定向到登录页
response.sendRedirect("/login.jsp");
return;
}
// 3. 已登录,放行请求(让请求继续走向Servlet)
chain.doFilter(request, response);
}
// init和destroy方法默认空实现,可省略
}
关键点:
@WebFilter("/order/*"):指定拦截的 URL(/*拦截所有请求)chain.doFilter(...):必须调用,否则请求会被 “拦死”(就像保安不让进也不让出)
三、监听器(Listener)—— 应用的 “监控摄像头”
1. 核心概念:监听器监听什么?
监听器就像 “监控摄像头”,默默盯着 Web 应用中的三大域对象(请求、会话、应用)的一举一动:
- ServletContextListener:监控应用启动 / 销毁(如加载全局配置)
- HttpSessionListener:监控用户会话创建 / 销毁(如统计在线人数)
- ServletRequestListener:监控请求创建 / 销毁(如记录访问日志)
2. 最常用的监听器:统计在线人数
以在线书店为例,用 HttpSessionListener 统计当前在线用户数:
// 在线人数监听器
@WebListener
public class OnlineCountListener implements HttpSessionListener {
private int onlineCount = 0; // 在线人数
// 会话创建时(用户登录/首次访问)
@Override
public void sessionCreated(HttpSessionEvent se) {
onlineCount++;
// 把在线人数存到应用域(所有用户共享)
se.getSession().getServletContext().setAttribute("onlineCount", onlineCount);
}
// 会话销毁时(用户退出/超时)
@Override
public void sessionDestroyed(HttpSessionEvent se) {
onlineCount--;
se.getSession().getServletContext().setAttribute("onlineCount", onlineCount);
}
}
在 JSP 中显示在线人数:
<!-- 在线书店首页 -->
当前在线人数:${applicationScope.onlineCount}人
为什么能统计?
- 用户打开浏览器访问网站 → 创建 Session →
sessionCreated触发 → 人数 + 1 - 用户关闭浏览器 / 超时 → Session 销毁 →
sessionDestroyed触发 → 人数 - 1
四、过滤器 vs 监听器:怎么选?
| 功能 | 过滤器(Filter) | 监听器(Listener) |
|---|---|---|
| 核心作用 | 拦截请求 / 响应,修改内容 | 监听事件,被动触发操作 |
| 使用场景 | 登录验证、编码处理、敏感词过滤 | 统计在线人数、加载全局配置 |
| 触发方式 | 主动拦截请求 | 被动监听事件(如 Session 创建) |
一句话总结:需要 “拦请求” 用过滤器,需要 “盯事件” 用监听器。
五、小白避坑指南
-
过滤器别忘了放行!
如果在doFilter中忘记调用chain.doFilter(request, response),请求会被永久拦截(用户永远看不到页面)。 -
监听器注册要正确
- 注解方式:用
@WebListener标注类 - XML 方式:在
web.xml中配置<listener>标签
两种方式选一种,不要重复注册。
- 注解方式:用
-
过滤器链的执行顺序
多个过滤器时,注解配置按类名字母顺序执行(如AFilter比BFilter先执行),XML 配置按<filter-mapping>顺序执行。
六、总结:过滤器和监听器的价值
- 过滤器:Web 应用的 “守门人”,帮你挡掉非法请求、统一处理通用逻辑(如编码)。
- 监听器:Web 应用的 “千里眼”,帮你监控应用状态、统计关键数据(如在线人数)。
下一篇我们将学习 “会话管理”,敬请期待
更多推荐
所有评论(0)