【JavaWeb学习 | 第19篇】Filter过滤器(过滤器)
在上一篇文章中,我们学习了 Servlet + JSP + JavaBean 的 MVC开发模式,代码结构已经清晰了很多。
但实际开发中还会遇到一些通用的、重复的处理逻辑,例如:
- 统一字符编码(解决中文乱码)
- 登录权限检查(未登录用户不能访问后台页面)
- 敏感词过滤
- 访问日志记录
- 防止SQL注入、XSS攻击等
如果把这些逻辑写在每一个Servlet里,就会造成大量代码重复,违背“DRY”(Don’t Repeat Yourself)原则。
Filter(过滤器) 正是为了解决这类问题而生的!
一、什么是Filter?
Filter 是 Servlet规范中提供的一个接口,位于 javax.servlet 包下。
它可以在 请求到达Servlet之前 或 响应返回浏览器之前 对请求和响应进行拦截和处理。
Filter的执行位置(非常重要):
浏览器 → Filter1 → Filter2 → ... → FilterN → Servlet(Controller) → JSP(View) → FilterN → ... → Filter1 → 浏览器
Filter可以有多个,它们按照配置顺序依次执行,形成过滤器链(Filter Chain)。
二、Filter的核心作用
- 预处理:请求到达Servlet之前做统一处理(编码、权限校验、日志等)
- 后处理:响应返回浏览器之前做统一处理(压缩、添加水印等)
- 拦截:不符合条件时直接阻止请求继续向下传递
三、Filter的开发步骤(超详细)
1. 编写Filter类(实现Filter接口)
// com.example.filter.EncodingFilter.java
package com.example.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/*") // 使用注解配置,拦截所有请求
public class EncodingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// Filter初始化时执行一次(类似Servlet的init)
System.out.println("EncodingFilter 初始化...");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// ===== 前置处理(请求进来时)=====
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
System.out.println("EncodingFilter 前置处理完成");
// ===== 关键:放行请求,让其继续往下走(到达下一个Filter或Servlet)=====
chain.doFilter(request, response);
// ===== 后置处理(响应返回时)=====
System.out.println("EncodingFilter 后置处理完成");
}
@Override
public void destroy() {
// Filter被销毁时执行一次(服务器关闭时)
System.out.println("EncodingFilter 销毁...");
}
}
2. 配置Filter(两种方式)
方式一:注解配置(推荐,Servlet 3.0+)
@WebFilter(
urlPatterns = {"/*"}, // 拦截路径
dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD}
)
public class EncodingFilter implements Filter { ... }
方式二:web.xml配置(传统方式)
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.example.filter.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
四、常用Filter示例
示例1:登录权限过滤器(最实用!)
@WebFilter("/*")
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// 1. 获取当前请求路径
String uri = request.getRequestURI();
// 2. 放行登录相关页面和资源
if (uri.contains("/login") || uri.contains("/register")
|| uri.endsWith(".css") || uri.endsWith(".js")
|| uri.endsWith(".png") || uri.endsWith(".jpg")) {
chain.doFilter(request, response);
return;
}
// 3. 检查session中是否有用户
Object user = request.getSession().getAttribute("user");
if (user != null) {
// 已登录,放行
chain.doFilter(request, response);
} else {
// 未登录,跳转到登录页
request.setAttribute("errorMsg", "请先登录!");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
}
示例2:XSS攻击简单过滤(字符替换)
public class XssFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 包装request,增强getParameter方法进行XSS过滤
XssHttpServletRequestWrapper wrapper = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(wrapper, response);
}
}
(实际生产中推荐使用成熟的XSS过滤框架,如OWASP Java Encoder)
五、Filter的重要知识点
- 多个Filter执行顺序:
- 注解方式:按照类名首字母顺序执行(不推荐依赖此顺序)
- web.xml方式:按照
<filter-mapping>在web.xml中出现的顺序执行(推荐) - FilterChain.doFilter():必须调用!否则请求会被拦截,无法到达Servlet。
- Filter的生命周期:
- 服务器启动时 →
init() - 每次请求 →
doFilter() - 服务器关闭时 →
destroy()
- Filter可以拦截:Request、Forward、Include、Error 等多种分发器类型。
六、实际开发建议
- 通用功能(编码、日志、权限)优先考虑用Filter实现。
- 权限控制通常结合Session + Filter + MVC一起使用。
- 不要在Filter中写复杂业务逻辑,Filter只做“通用预处理/后处理”。
- Filter执行顺序很重要,敏感操作的过滤器要放在前面。
- 现代项目中,Spring Boot常用 Interceptor(拦截器)和 HandlerExceptionResolver 替代部分Filter功能,但Filter仍是JavaWeb基础必须掌握的内容。
七、练习建议(动手实践很重要!)
- 实现全局字符编码过滤器(解决所有中文乱码问题)。
- 编写登录权限过滤器,保护后台管理页面(
/admin/*)。 - 实现一个简单的访问日志过滤器,记录每次请求的IP、URI、时间。
- 尝试配置多个Filter,观察执行顺序(一个编码过滤器 + 一个登录过滤器)。
完成这些练习后,你会明显感觉到项目代码变得更加优雅和专业!
系列文章导航(持续更新中):
- 第17篇:JSP内置对象
- 第18篇:Servlet与MVC
- 第19篇:Filter过滤器(本文)
- 第20篇:Listener监听器(在线人数统计、Session监听等)
下一篇文章预告:我们将学习 Listener(监听器),它能监听ServletContext、HttpSession、ServletRequest的创建、销毁和属性变化,是实现“在线人数统计”、“实时聊天”等功能的核心技术。
有任何疑问(比如多个Filter的顺序如何精确控制、或XssFilter如何实现),欢迎在评论区留言,我会及时补充详细代码!
继续加油!你正在从“会用Servlet+JSP”逐步走向“能搭建完整JavaWeb项目”的阶段!🔥
下一篇文章见~ 🚀