Java Servlet Filter 运行在容器层面,需通过web.xml或@WebFilter注册,核心方法init()、doFilter()、destroy()必须全部实现,其中doFilter()须调用chain.doFilter()放行,否则请求中断。
Java Servlet Filter 不是拦截器,也不等价于 Spring 的 @Component 过滤器;它运行在容器(如 Tomcat)层面,必须通过或注册才能生效,否则代码写了也完全不触发。
Filter 接口的三个核心方法怎么用
实现
接口时,必须重写
、
、
。其中只有
是业务逻辑入口,其余两个生命周期方法常被误认为可省略 —— 实际上若不显式实现,编译会通过但容器启动可能报
(尤其在旧版 Tomcat 中)。
关键点:
必须调用
才能放行,漏掉这句会导致后续所有 Servlet / Filter 不执行,页面空白且无错误日志
中可通过
读取
,这是传参唯一合法方式,不能靠构造函数或静态变量
不保证在 JVM 退出前一定被调用,不适合放资源强释放逻辑(比如未关闭的数据库连接)
@WebFilter 注解注册 vs web.xml 配置的区别
两者功能等价,但行为细节不同:使用
时,类必须是 top-level class(不能是 private static inner class),且扫描依赖
(默认值)和正确的
版本声明(如
)。而
方式更稳定,尤其在混合使用 Jersey、Spring Boot 嵌入式容器时。
立即学习
“
Java免费学习笔记(深入)
”;
常见陷阱:
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
会匹配所有请求,包括静态资源(
),若在 filter 中做了字符
编码
设置,可能干扰图片/字体响应
在
中不支持通配符结尾以外的形式,比如
无效,必须用
+ 手动路径判断
多个 filter 的执行顺序由注册顺序决定:
中靠前的先执行;
则按类加载顺序,不可控,需用
+
显式约束
如何安全地修改 request / response 内容
原生
和
是只读包装,直接调用
或
在
中可能失败(例如已提交响应头后写 body 会抛
)。正确做法是继承
和
。
典型场景示例(修改请求体):
注意:
不要在 filter 中反复调用
或
,Servlet 规范明确禁止多次读取原始流
若要改写响应内容(如添加 JSON 外壳),必须用
包装并覆写
/
,否则写入会被丢弃
字符编码应在
前调用
,但对 GET 请求无效(参数编码由容器在解析 URL 时决定)
Filter 的真正难点不在写法,而在它介入的是容器最底层的 I/O 流链路 —— 任何异常都可能中断整个请求生命周期,且调试时看不到栈中 filter 的上下文。线上环境务必加 try-catch 并记录原始
,否则连哪条路径触发的问题都难以定位。
web.xml@WebFilterjavax.servlet.Filterinit()doFilter()destroy()doFilter()NoClassDefFoundErrordoFilter()chain.doFilter(request, response)init()filterConfig.getInitParameter("xxx")destroy()@WebFiltermetadata-complete="false"web.xmlversion="4.0"web.xml@WebFilter(urlPatterns = "/*")/css/app.css/api/* web.xml/api/v1/.*/*web.xml@WebFilterfilterNamedispatcherTypesHttpServletRequestHttpServletResponserequest.setAttribute()response.getWriter().write()doFilter()IllegalStateExceptionHttpServletRequestWrapperHttpServletResponseWrapperpublic class BodyCachingRequestWrapper extends HttpServletRequestWrapper {
private final byte[] cachedBody;
public BodyCachingRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
InputStream stream = request.getInputStream();
this.cachedBody = stream.readAllBytes(); // Java 9+
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new ByteArrayInputStream(cachedBody).asInputStream();
}
}request.getInputStream()request.getReader()HttpServletResponseWrappergetWriter()getOutputStream()chain.doFilter()request.setCharacterEncoding("UTF-8")request.getRequestURL()