过滤器filter简介
Filter是Servlet规范的三大组件 之一,另外两个分别 是 Servlet和 listener.filter的 中文意思是 过滤,可以在请求到达 目标资源之前 先对请求 进行拦截 过滤,即对请求 进行一些处理;也可以 在响应达到 客户端之前 先对响应 进行拦截过滤,即 对响应 进行一些处理。
Web开发人员通过Filter技术,可以对Web服务器 管理的所有Web资源:例如Jsp,Servlet,静态图片文件或静态html文件等进行拦截,从而实现 一些特殊的功能。例如实现URL级别的权限 访问控制、过滤敏感词汇、压缩响应信息、计算系统的响应时间等一些高级功能。
在Servlet规范中,有一个Javax.servlet.Filter接口。实现了该接口的类称为 过滤器,接口中有三个方法可以重写:
- init():初始化方法,即Filter被创建后,在后面用到的资源的初始化工作,可以在这里完成。
- doFilter():Filter的核心方法,对于请求与相应的过滤,就是在这个方法中完成的。
- destroy():销毁方法。Filter被销毁前所调用的执行的方法。对于资源的释放工作,可以在这里完成。
,
创建Filter过滤器的步骤
- 创建一个类实现javax.servlet.Filter接口
- 重写接口中的方法
- 在web.xml文件配置Filter
注意:在Filter的doFilter方法内如果没有执行doFilter(request,response)方法,那么服务器中的资源 是不会 被访问到的。
Filter的生命周期
- 当服务器启动时,会创建Filter对象,并调用init方法,只调用一次。
- 当访问资源时,路径 与Filter的拦截 路径匹配,会执行Filter中的doFilter方法,这个方法是真正拦截操作的方法。
- 当服务器关闭时,会调用Filter的destory方法来进行销毁操作
一个Filter的生命周期 跟servlet有些类似,需要经历 实例化–>初始化–>doFilter–>销毁四个过程。
Filter的匹配路径
Filter的全匹配路径只支持/*,不支持/
Filter特征
- Filter是单例多线程的。
- Filter是在应用被加载时创建并初始化,这是与Servlet不同的地方。Servlet是在该Servlet被第一次 访问时创建。Filter与Servlet的共同特点是,其无参 构造器 与 init()方法只会执行一次。
- 用户每提交一次该Filter可以 过滤的请求,服务器就会执行一次doFilter()方法,即doFilter()方法是 可以被多次执行的。
- 当应用被停止时 执行destory()方法,Filter被销毁,即destory()方法只会执行一次。
- 由于Filter是 单例多线程的,所以为了 保证 其线程安全性,一般情况下 是不为Filter类定义可修改的成员变量的。因为 每个 线程 均可修改 这个成员变量,会出现线程安全问题。
多个Filter的执行 过程
若web应用 中配置 了多个Filter,那么这些Filter的执行过程是以链的方式执行的,即会将这些 与请求匹配的Filter串成一个可执行的 链,然后 按照这个链中的顺序依次执行。这些Filter在链 中的顺序 与他们在web.xml中的注册 顺序 相同,即 web,xml中的注册顺序就是Filter的执行顺序。一个 Filter的执行完毕,转而 执行另一个 Filter,这个转向 工作 是由 FilterChain的doFilter()方法完成的,当然,若当前Filter是最后一个Filter,则FilterChain的doFilter()会自动转向最终的请求资源。 当请求 到达Filter后,Filter可以拦截到请求对象,并对请求进行 修改。修改过后,再将修改过的请求 转向 下一个 资源。
当 最终的资源执行完毕,并形成响应对象后,会按照 请求访问 Filter的倒序,再次 访问Filter。此时Filter可以拦截到 响应对象,并 对响应 进行修改。最终,客户端 可以收到 已被 修改过的响应。
例子:使用 Filter解决 乱码的问题
在之前 编写Servlet时 ,需要 在 每个 servlet中声明 编码,这种方式 比较繁琐,下面 使用Filter 解决该问题: