Filter 详解
前言
在 Java Web 开发中,你是否遇到过这样的需求:
- 用户必须登录才能访问订单页面
- 所有请求统一设置 UTF-8 编码避免乱码
- 记录每个请求的访问日志用于审计
- 防止跨站脚本攻击(XSS)
- 响应数据压缩以提升性能
这些看似分散的功能,其实都可以通过一个强大的机制统一实现:Filter(过滤器)。
Filter 就像网站的“保安”或“安检门”,它在请求到达业务逻辑之前、响应返回客户端之前,进行拦截、检查、处理,是构建安全、高效 Web 应用的基石。
一、Filter概述
Filter(过滤器)是 Java Servlet 规范中提供的一种组件,用于在请求到达目标资源(如 Servlet、JSP 等)之前或响应返回客户端之前,对请求和响应进行拦截和处理。
过滤器,顾名思义就是对事物进行过滤的,在Web中的过滤器,当然就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。如登录控制,权限管理,过滤敏感词汇等.
✅ 类比理解:就像“安检门”一样,所有进入 Web 应用的请求都必须先经过 Filter 的检查和处理。
- 所属包:
jakarta.servlet.Filter(Servlet 5.0+ 使用jakarta,旧版本为javax.servlet) - 作用范围:可对指定 URL 路径、Servlet 或整个应用进行统一控制。
- 特点:
- 不生成响应内容
- 可以决定是否放行请求
- 支持链式调用(多个 Filter 组成过滤器链)
核心概念
过滤器的核心功能是拦截请求和响应,并在拦截过程中执行特定的逻辑。它通过
doFilter()方法实现对请求和响应的处理,并通过FilterChain对象调用下一个过滤器或目标资源。
二、Filter 的核心作用
| 作用 | 典型场景 |
|---|---|
| 权限控制 | 登录校验、角色权限验证 |
| 编码处理 | 统一设置请求/响应字符编码(UTF-8) |
| 日志记录 | 记录请求路径、IP、耗时等 |
| 安全防护 | XSS 过滤、CSRF 防护、IP 黑名单 |
| 性能优化 | 响应压缩(GZIP)、缓存控制 |
| 请求改造 | 修改请求头、包装 Request |
| 响应改造 | 修改响应头、包装 Response |
三、过滤器原理
3.1 请求在Tomcat中的执行流程

看过Tomcat详解的都知道,
Container处理请求是使用Pipeline-Valve管道来处理的!
Pipeline-Valve是责任链模式
Pipeline管道分为First首节点和Basic基础节点,基础节点用于调用下一层容器,处于当前容器职责链的末尾,最后执行
也就是每层容器中职责链的调用顺序从First开始Basic结束
我们知道Container包含四个子容器,而这四个子容器对应的BaseValve分别在:StandardEngineValve、StandardHostValve、StandardContextValve、StandardWrapperValve。
也就是说:
1)Connector在接收到请求后会首先调用最顶层容器的Pipeline来处理,这里的最顶层容器的Pipeline就是EnginePipeline(Engine的管道);
(2)在Engine的管道中依次会执行EngineValve1、EngineValve2等等,最后会执行StandardEngineValve,在StandardEngineValve中会调用Host管道,然后再依次执行Host的HostValve1、HostValve2等,最后在执行StandardHostValve,然后再依次调用Context的管道和Wrapper的管道,最后执行到StandardWrapperValve。
(3)当执行到StandardWrapperValve的时候,会在StandardWrapperValve中调用ApplicationFilterFactory.createFilterChain(request, wrapper, servlet)方法创建FilterChain,并调用其doFilter方法来处理请求,这个FilterChain包含着我们配置的与请求相匹配的Filter和Servlet,其doFilter方法会依次调用所有的Filter的doFilter方法和Servlet的service方法,这样请求就得到了处理!
StandardWrapperValue源码中的invoke()方法佐证:
public void invoke(Request request, Response response) throws IOException, ServletException {
//省略...
// Create the filter chain for this request
ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
//省略...
}
(4)当所有的Pipeline-Value都执行完之后,并且处理完了具体的请求,这个时候就可以将返回的结果交给Connector了,Connector在通过Socket的方式将结果返回给客户端。
FilterChain 是一个责任链,它从第一个 Filter 开始执行,经过所有 Filter 的 doFilter(),最终“放行”到 Servlet.service() 方法,而 Servlet.service() 是这个链的最后一个节点。

- 请求阶段:从前向后依次执行每个 Filter 的前置逻辑。
- 调用
chain.doFilter()后,继续向下传递。 - 到达目标资源(如 Servlet)并处理完成后,响应沿原路返回,执行各 Filter 的后置逻辑。
3.2 过滤器(Filter)接口
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
}
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
default void destroy() {
}
}
init():获取配置信息,初始化资源。doFilter():核心业务逻辑,决定是否放行。destroy():释放资源,如关闭数据库连接等。
我们通过官方提供的过滤器可以看出过滤器(Filter)使用起来还是比较简单的,下面我们就来学习如何使用过滤器(Filter)
3.3 创建过滤器(Filter)
创建Filter,只需要继承Filter接口就行。
- 创建实现类实现
jakarta.servlet.Filter接口; - 重写
doFilter()方法,编写拦截逻辑;
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//放行
filterChain.doFilter()
}
}
如果某个 Filter 中没有调用
filterChain.doFilter(),则请求被“拦截”,后续资源不会被执行。Filter接口有3个方法,但是只有一个方法没有实现,我们只需要实现这个方法就行。我们可以发现,我们实现了一个doFilter方法,这个方法就是我们写过滤代码的地方,具体逻辑就是和上面介绍的过滤器原理一样的。
3.4 使用过滤器(Filter)
如何使用过滤器,使用它我们就要对它进行配置
配置过滤器主要有两种方式
方式一:注解方式
@WebFilter("/ServletA") // 拦截指定路径
// @WebFilter("*.html") // 拦截所有 .html 文件
// @WebFilter("/*") // 拦截所有请求
public class MyFilter implements Filter { ... }
方式二:web.xml 配置
<!-- 注册过滤器 -->
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.zzz.filter.MyFilter</filter-class>
</filter>
<!-- 映射过滤规则 -->
<filter-mapping>
<filter-name>LoggingFilter</filter-name>
<!-- 拦截方式任选其一或组合 -->
<!-- <url-pattern>/*</url-pattern> -->
<servlet-name>ServletA</servlet-name>
</filter-mapping>
当我们的Servlet注册和映射时
比如
@WebServlet(value = "/ServletA",name = "ServletA")或者
<servlet> <servlet-name>ServletA</servlet-name> <servlet-class>com.zzz.servlet.ServletA</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletA</servlet-name> <url-pattern>/ServletA</url-pattern> </servlet-mapping>我们在配置过滤器的映射过滤规则时,可以使用servlet-name标签
<!-- 映射过滤规则 --> <filter-mapping> <filter-name>LoggingFilter</filter-name> <servlet-name>ServletA</servlet-name> </filter-mapping>或者
@WebFilter(servletNames = "ServletA")
测试
//通过注解的方式进行配置
@WebFilter("/ServletA")
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " MyFilter开始执行");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " MyFilter执行完毕");
}
}
@WebServlet(value = "/ServletA",name = "ServletA")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " ServletA开始执行");
try {
Thread thread = new Thread();
thread.sleep(5000);
}catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " ServletA执行完毕");
}
}
我们访问http://localhost:8080/JavaWeb_05/ServletA

可以看到,我们的请求经过过滤器时执行了 MyFilter开始执行,随后执行filterChain.doFilter(servletRequest, servletResponse),进行放行,执行ServletA.service()方法,执行完毕后进行响应,响应的时候会再次经过过滤器的过滤,执行了 MyFilter执行完毕。
此过程验证了我们上面讲述的请求在Tomcat中是如何经过Filter的。
3.5 Filter 的生命周期(由 Servlet 容器管理)
Filter 的生命周期由 Web 容器(如 Tomcat)控制,分为四个阶段:
| 阶段 | 方法 | 调用时机 | 调用次数 |
|---|---|---|---|
| 实例化 | 构造函数 | Tomcat 容器在 Context 初始化阶段 | 1 次 |
| 初始化 | init(FilterConfig config) | Tomcat 容器在 Context 初始化阶段 | 1 次 |
| 过滤处理 | doFilter(ServletRequest, ServletResponse, FilterChain) | 每次请求匹配时 | N 次 |
| 销毁 | destroy() | Tomcat 容器关闭时 | 1 次 |
类比:就像保安的上班流程:打卡(构造)→ 接收任务(init)→ 检查人员(doFilter)→ 下班(destroy)
测试
public class LifecycleFilter implements Filter {
public LifecycleFilter() {
System.out.println("LifecycleFilter 构造方法");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("LifecycleFilter init方法");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("LifecycleFilter doFilter方法");
}
@Override
public void destroy() {
System.out.println("LifecycleFilter destroy方法");
}
@WebServlet(value = "/ServletA",name = "ServletA")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletA开始执行");
try{
Thread thread = new Thread();
thread.sleep(5000);
} catch (Exception e) {
throw new RuntimeException(e);
}
System.out.println("ServletA执行完毕");
}
}
<filter>
<filter-name>LifecycleFilter</filter-name>
<filter-class>com.zzz.filter.LifecycleFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LifecycleFilter</filter-name>
<url-pattern>/ServletA</url-pattern>
</filter-mapping>
Tomcat启动时,在 Context 初始化阶段,先执行构造函数,在执行init方法

每次请求匹配时

Tomcat 容器关闭时
经过测试,我们基本可以理解Filter的生命周期。
3.6 FilterConfig和FilterChain
FilterConfig和FilterChain这2个对象是由服务器(Tomcat)在创建和调用Filter对象时所传入的,这2个对象十分有用,FilterConfig对象可以读取我们配置的初始参数,FilterChain可以实现多个Filter之间的连接。
在 Servlet 规范中,FilterConfig 和 FilterChain 是过滤器(Filter)机制中两个核心的接口对象,均由服务器(如 Tomcat)在运行时自动创建并传入,开发者无需手动实例化。它们分别承担配置管理和执行流程控制的职责。
3.6.1 FilterConfig
FilterConfig 是容器在初始化 Filter 时传入的配置对象,用于:
- 获取
web.xml或@WebFilter注解中配置的初始化参数(init-param) - 获取
ServletContext对象,进而访问全局上下文信息
生命周期
- 在
Filter.init(FilterConfig config)方法中传入 - 整个
Filter生命周期中只传入一次 Filter实例可通过该对象持久持有配置信息
public interface FilterConfig {
String getFilterName();
ServletContext getServletContext();
String getInitParameter(String name);
Enumeration<String> getInitParameterNames();
}
| 方法 | 说明 |
|---|---|
String getInitParameter(String name) | 获取指定名称的初始化参数 |
Enumeration<String> getInitParameterNames() | 获取所有初始化参数的名称 |
String getFilterName() | 获取 <filter-name> 的值 |
ServletContext getServletContext() | 获取全局上下文对象 |
测试
public class MyFilterConfig implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String filterName = filterConfig.getFilterName();
System.out.println("MyFilterConfig初始化方法,过滤器名称:" + filterName);
ServletContext servletContext = filterConfig.getServletContext();
System.out.println("MyFilterConfig初始化方法,ServletContext对象:" + servletContext);
String username = filterConfig.getInitParameter("username");
System.out.println("MyFilterConfig初始化方法,username参数:" + username);
Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
while(initParameterNames.hasMoreElements()){
String name = initParameterNames.nextElement();
System.out.println(name+" = "+filterConfig.getInitParameter(name));
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
}
}
<filter>
<filter-name>MyFilterConfig</filter-name>
<filter-class>com.zzz.filter.MyFilterConfig</filter-class>
<init-param>
<param-name>username</param-name>
<param-value>zhangsan</param-value>
</init-param>
<init-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</init-param>
<init-param>
<param-name>DriverClass</param-name>
<param-value>com.mysql.cj.jdbc.Driver</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFilterConfig</filter-name>
<url-pattern>/ServletA</url-pattern>
</filter-mapping>
或者通过注解配置
@WebFilter(initParams = {@WebInitParam(name = "username",value = "张三"),
@WebInitParam(name = "password",value = "123456")
},value = "/ServletA")
我们重启项目:因为FilterConfig是在 Filter.init(FilterConfig config) 方法中传入,整个 Filter 生命周期中只传入一次

3.6.2 FilterChain
过滤器链,实现责任链模式
作用
FilterChain 是 Servlet 容器动态构建的责任链(Chain of Responsibility),用于:
- 按照配置顺序依次调用多个
Filter的doFilter()方法 - 在所有
Filter执行完毕后,最终调用目标Servlet的service()方法
核心机制
- 动态构建:每次请求到达时,Tomcat 根据请求 URL 匹配所有有效的
Filter,并按<filter-mapping>顺序组装成FilterChain - 顺序执行:每个
Filter调用chain.doFilter(request, response)表示“放行”到下一个处理者 - 终点是 Servlet:链的最后一个节点是目标
Servlet,调用servlet.service()
- 如果某个
Filter没有调用chain.doFilter(),请求将被拦截,后续Filter和Servlet都不会执行- 多个
Filter可以形成“环绕”效果:前处理 → 下一个 → 后处理
public interface FilterChain {
void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException;
}
我们查看源码,可以发现FilterChain就只有一个方法,其实这个方法就是用来对过滤器的拦截进行放行的,如果有多个过滤器,那么就会继续调用下一个Filter进行拦截。doFilter方法需要传入个参数,一个是ServletRequest,一个是ServletResponse,这个直接传入进行。
Tomcat在调用过滤器时,默认就会传入Request和Response,这个参数封装了请求和响应,我们直接使用就行。ServletResquest和ServletResponse可以直接强转成HttpServletRequest和HttpServletResponse,然后使用相应的方法。
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
}
| 接口 | 特点 |
|---|---|
ServletRequest / ServletResponse | 通用接口,适用于任何协议(如 FTP、自定义协议等) |
HttpServletRequest / HttpServletResponse | HTTP 专用,提供了所有 HTTP 相关的操作方法 |
在 Web 应用中,我们处理的几乎都是 HTTP 请求,所以必须转成 HTTP 子类型才能进行实际操作。
测试
我们多写几个过滤器,通过FilterChain来进行多个过滤。
直接通过注解进行注册和映射。
@WebFilter("/ServletB")
public class MyFilter01 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " MyFilter01开始执行");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " MyFilter01执行完毕");
}
}
@WebFilter("/ServletB")
public class MyFilter02 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " MyFilter02开始执行");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " MyFilter02执行完毕");
}
}
@WebFilter("/ServletB")
public class MyFilter03 implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " MyFilter03开始执行");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " MyFilter03执行完毕");
}
}
@WebServlet(value = "/ServletB",name = "ServletB")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " ServletB开始执行");
try {
Thread thread = new Thread();
thread.sleep(5000);
}catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + " ServletB执行完毕");
}
}
我们访问http://localhost:8080/JavaWeb_05/ServletB
可以看到我们配置的多个过滤器生效,请求时过滤,响应时也会过滤。
那么我们怎么指定多个Filter的执行顺序呢?
3.7 多个Filter的执行顺序
FilterChain 中多个过滤器的执行顺序,是由它们在 web.xml 中的 <filter-mapping> 配置顺序决定的 —— 谁先声明,谁先执行。
不是按 <filter> 声明顺序,而是按 <filter-mapping> 的声明顺序!
方式一:使用 web.xml 配置
<filter>
<filter-name>MyFilter01</filter-name>
<filter-class>com.zzz.filter.MyFilter01</filter-class>
</filter>
<filter>
<filter-name>MyFilter02</filter-name>
<filter-class>com.zzz.filter.MyFilter02</filter-class>
</filter>
<filter>
<filter-name>MyFilter03</filter-name>
<filter-class>com.zzz.filter.MyFilter03</filter-class>
</filter>
<!-- 关键来了:mapping 的顺序决定执行顺序 -->
<filter-mapping>
<filter-name>MyFilter03</filter-name>
<url-pattern>/ServletB</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>MyFilter02</filter-name>
<url-pattern>/ServletB</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>MyFilter01</filter-name>
<url-pattern>/ServletB</url-pattern>
</filter-mapping>
测试
我们访问http://localhost:8080/JavaWeb_05/ServletB

此时可以发现顺序是按我们在web.xml中filter-mapping映射的顺序进行执行的。
方式二:使用注解
默认情况(无顺序控制):
@WebFilter("/*")
public class MyFilter01 implements Filter { ... }
@WebFilter("/*")
public class MyFilter02 implements Filter { ... }
@WebFilter("/*")
public class MyFilter03 implements Filter { ... }
使用 @Order 或 @Priority(需配合 Spring)
如果你在 Spring Boot 环境下:
@Order(1)
@WebFilter("/*")
public class MyFilter01 implements Filter { ... }
@Order(2)
@WebFilter("/*")
public class MyFilter02 implements Filter { ... }
@Order(3)
@WebFilter("/*")
public class MyFilter03 implements Filter { ... }
✅
@Order(n)数值越小,优先级越高,越早执行。
⚠️ 注意:原生 Servlet 容器(如纯 Tomcat)不识别 @Order,它来自 Spring 框架。
四、Filter应用实例(实现敏感词汇过滤)
写一个评论页面,可以进行评论,如果评论中含有我们定义的敏感词汇,那么我们就进行过滤,使用***来进行代替。
@WebFilter(value = "/comment",initParams = {@WebInitParam(name = "words1",value = "zz"),
@WebInitParam(name = "words2",value = "sb")})
public class SensitiveWordFilter implements Filter {
private List<String> sensitiveWords = new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
while(initParameterNames.hasMoreElements()){
String name = initParameterNames.nextElement();
System.out.println(name+" = "+filterConfig.getInitParameter(name));
sensitiveWords.add(filterConfig.getInitParameter(name));
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//设置编码
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//获得评论
String comment = request.getParameter("comment");
for (String sensitiveWord : sensitiveWords) {
if (comment.contains(sensitiveWord)) {
String newComment = comment.replace(sensitiveWord, "***");
comment = newComment;
} else {
System.out.println("未匹配");
}
}
//存入request域
request.setAttribute("comment",comment);
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
}
@WebServlet("/comment")
public class CommentServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置编码
req.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
//获得评论
String comment = req.getAttribute("comment").toString();
if(comment.contains("***")){
resp.getWriter().write("<p> bad boy :"+comment + "</p>");
}else{
resp.getWriter().write("<p> good boy :"+comment + "</p>");
}
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>敏感词汇过滤</title>
</head>
<body>
<h1>敏感词汇过滤</h1>
<h2>请输入评论:</h2>
<form action="comment" method="post">
<textarea id="comment" name="comment" rows="5" cols="40"></textarea>
<input type="submit" value="提交">
</form>
</body>
</html>
我们通过设置注解配置过滤器的初始化值,设置了两个zz和sb
在初始化阶段,通过FilterConfig获得两个初始化参数将他们存入我们的List集合中
在doFilter()方法中,我们通过request对象获得我们前端输入的comment,此时我们进行过滤,当包含我们的敏感词时,对他进行一个替换,并将它重新设置回request对象中,此时过滤完毕放行。
放行后到达我们的CommentServlet,我们从request对象中获得过滤过的comment,判断comment是否含有***,也就是我们过滤的替换标志,然后通过不同的情况,设置response对象。
我们输入你是一个好人

我们输入你是一个zz


此时我们的敏感词过滤就成功了。
总结
Filter 是 Java Web 中用于拦截请求和响应的组件,可在到达 Servlet 前进行权限校验、编码设置、日志记录、敏感词过滤等处理。它通过 doFilter() 方法实现逻辑,并由 FilterChain 控制多个过滤器的执行顺序。配置方式有注解和 web.xml 两种,生命周期由容器管理,是实现通用功能解耦的核心技术。
浙公网安备 33010602011771号