跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Java过滤器Filter_Java Servlet Filter接口详解与使用方法

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

相关文章