详解 Filter 过滤器
1、简介
Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
它主要用于对用户请求进行预处理,也可以对HttpServletResponse 进行后处理。使用Filter 的完整流程:Filter 对用户请求进行预处理,接着将请求交给Servlet 进行处理并生成响应,最后Filter 再对服务器响应进行后处理。
Filter功能:
- 在HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest 。 根据需要检查 HttpServletRequest ,也可以修改HttpServletRequest 头和数据。
- 在HttpServletResponse 到达客户端之前,拦截HttpServletResponse 。 根据需要检查 HttpServletResponse ,也可以修改HttpServletResponse头和数据。
2、如何实现拦截
Filter接口中有一个doFilter方法,当开发人员编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:
- 调用目标资源之前,让一段代码执行。
- 是否调用目标资源(即是否让用户访问web资源)。
web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。
3、Filter开发两步走
- 编写java类实现Filter接口,并实现其doFilter方法。
- 在 web.xml 文件中使用和元素对编写的filter类进行注册,并设置它所能拦截的资源。
web.xml配置各节点介绍:
1 |
<filter-name>用于为过滤器指定一个名字,该元素的内容不能为空。 |
4、Filter链
在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。
web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
多个过滤器执行顺序
一个目标资源可以指定多个过滤器,过滤器的执行顺序是在web.xml文件中的部署顺序:
1 |
<filter> |
MyFilter1
1 |
public class extends HttpFilter { |
MyFilter2
1 |
public class MyFilter2 extends HttpFilter { |
1 |
<body> |
当有用户访问index.jsp页面时,输出结果如下:
1 |
filter1 start... |
5、Filter的生命周期
1 |
public void init(FilterConfig filterConfig) throws ServletException;//初始化 |
和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
1 |
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;//拦截请求 |
这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL(目标资源)的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。
1 |
public void destroy();//销毁 |
服务器在创建Filter对象之后,把Filter放到缓存中一直使用(会驻留在内存),通常不会销毁它,当web应用移除或服务器停止时才销毁Filter对象。在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。
6、FilterConfig接口
用户在配置filter时,可以使用为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得以下内容:
1 |
String getFilterName();//得到filter的名称;与<filter-name>元素对应。 |
7、FilterChain
doFilter()方法的参数中有一个类型为FilterChain的参数,它只有一个方法:doFilter(ServletRequest,ServletResponse)
doFilter() 方法的放行,让请求流访问目标资源!其实调用该方法的意思是,当前 Filter 放行了,但不代表其他过滤器也放行。一个目标资源上,可能部署了多个过滤器,所以调用 FilterChain 类的 doFilter() 方法表示的是执行下一个过滤器的 doFilter() 方法,或者是执行目标资源!
如果当前过滤器是最后一个过滤器,那么调用 chain.doFilter() 方法表示执行目标资源,而不是最后一个过滤器,那么 chain.doFilter() 表示执行下一个过滤器的 doFilter() 方法。
8、过滤器的应用场景
- 执行目标资源之前做预处理工作,例如设置编码,这种试通常都会放行,只是在目标资源执行之前做一些准备工作;
- 通过条件判断是否放行,例如校验当前用户是否已经登录,或者用户IP是否已经被禁用;
- 在目标资源执行后,做一些后续的特殊处理工作,例如把目标资源输出的数据进行处理
设置目标资源
在web.xml文件中部署Filter时,可以通过“*”来执行目标资源:
1 |
<filter-mapping> |
特性与Servlet完全相同!通过这一特性,可以在用户访问敏感资源时,执行过滤器,例如:/admin/*,可以把所有管理员才能访问的资源放到/admin路径下,这时可以通过过滤器来校验用户身份。
还可以为指定目标资源为某个Servlet,例如:
1 |
<servlet> |
当用户访问http://localhost:8080/filtertest/abc
时,会执行名字为myservlet的Servlet,这时会执行过滤器。
9、四种拦截方式
写一个过滤器,指定过滤的资源为b.jsp,然后在浏览器中直接访问b.jsp,会发现过滤器执行了.但是,当在a.jsp中request.getRequestDispathcer(“/b.jsp”).forward(request,response)时,就不会再执行过滤器了!也就是说,默认情况下,只能直接访问目标资源才会执行过滤器,而forward执行目标资源,不会执行过滤器!
1 |
public class MyFilter extends HttpFilter { |
1 |
<filter> |
1 |
<body> |
1 |
<h1>a.jsp</h1> |
在浏览器输入:
http://localhost:8080/filtertest/b.jsp
直接访问b.jsp时,会执行过滤器内容;
http://localhost:8080/filtertest/a.jsp
访问a.jsp,但a.jsp会forward到b.jsp,这时就不会执行过滤器!
过滤器有四种拦截方式!分别是:REQUEST、FORWARD、INCLUDE、ERROR。
- REQUEST:直接访问目标资源时执行过滤器。包括:在地址栏中直接访问、表单提交、超链接、重定向,只要在地址栏中可以看到目标资源的路径,就是REQUEST
- FORWARD:转发访问执行过滤器。包括RequestDispatcher#forward()方法、标签都是转发访问
- INCLUDE:包含访问执行过滤器。包括RequestDispatcher#include()方法、标签都是包含访问
- ERROR:当目标资源在web.xml中配置为中时,并且真的出现了异常,转发到目标资源时,会执行过滤器。
可以在中添加0~n个子元素,来说明当前访问的拦截方式。
如:
1 |
<filter-mapping> |
最为常用的就是REQUEST和FORWARD两种拦截方式,而INCLUDE和ERROR都比较少用!其中INCLUDE比较好理解,ERROR方式不易理解,下面给出ERROR拦截方式的例子:
1 |
<filter-mapping> |
1 |
<body> |
10、Filter使用案例
1、使用Filter验证用户登录安全控制
前段时间参与维护一个项目,用户退出系统后,再去地址栏访问历史,根据url,仍然能够进入系统响应页面。我去检查一下发现对请求未进行过滤验证用户登录。添加一个filter搞定问题!
先在web.xml配置
1 |
<filter> |
接着编写FilterServlet:
1 |
package com.action.login; import java.io.IOException; import javax.servlet.Filter; |
这样既可完成对用户所有请求,均要经过这个Filter进行验证用户登录。
2、防止中文乱码过滤器
项目使用spring框架时。当前台JSP页面和JAVA代码中使用了不同的字符集进行编码的时候就会出现表单提交的数据或者上传/下载中文名称文件出现乱码的问题,那就可以使用这个过滤器。
1 |
<filter> |
3、Spring+Hibernate的OpenSessionInViewFilter控制session的开关
当 hibernate+spring 配合使用的时候,如果设置了lazy=true(延迟加载),那么在读取数据的时候,当读取了父数据后,hibernate 会自动关闭 session,这样,当要使用与之关联数据、子数据的时候,系统会抛出lazyinit的错误,这时就需要使用 spring 提供的 OpenSessionInViewFilter 过滤器。
OpenSessionInViewFilter主要是保持 Session 状态直到 request 将全部页面发送到客户端,直到请求结束后才关闭 session,这样就可以解决延迟加载带来的问题。
注意:OpenSessionInViewFilter 配置要写在struts2的配置前面。因为 tomcat 容器在加载过滤器的时候是按照顺序加载的,如果配置文件先写的是 struts2 的过滤器配置,然后才是 OpenSessionInViewFilter 过滤器配置,所以加载的顺序导致,action 在获得数据的时候 session 并没有被 spring 管理。
1 |
<!-- lazy loading enabled in spring --> |
4、Struts2的web.xml配置
项目中使用Struts2同样需要在web.xml配置过滤器,用来截取请求,转到Struts2的Action进行处理。
注意:如果在2.1.3以前的Struts2版本,过滤器使用org.apache.struts2.dispatcher.FilterDispatcher
。否则使用org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
。从Struts2.1.3开始,将废弃ActionContextCleanUp
过滤器,而在StrutsPrepareAndExecuteFilter
过滤器中包含相应的功能。
三个初始化参数配置:
- config参数:指定要加载的配置文件。逗号分割。
- actionPackages参数:指定Action类所在的包空间。逗号分割。
- configProviders参数:自定义配置文件提供者,需要实现ConfigurationProvider接口类。逗号分割。
1 |
<!-- struts 2.x filter --> |
-->
详解 Filter 过滤器的更多相关文章
- logback logback.xml常用配置详解 <filter>
<filter>: 过滤器,执行一个过滤器会有返回个枚举值,即DENY,NEUTRAL,ACCEPT其中之一.返回DENY,日志将立即被抛弃不再经过其他过滤器:返回NEUTRAL,有序列表 ...
- 79.常用的返回QuerySet对象的方法使用详解: filter, exclude,annotate
返回新的QuerySet的常用方法: 1.filter: 将满足条件的数据提取出来,返回一个新的QuerySet 以下所使用的模型article,category,定义模型models.py文件中,示 ...
- css filter详解
css filter详解 filter 属性详解 属性 名称 类型 说明 grayscale 灰度 值为数值 取值范围从0到1的小数(包括0和1) sepia 褐色 值为数值 取值范围从0到1的小数( ...
- logback logback.xml常用配置详解(三)
logback logback.xml常用配置详解 <filter> <filter>: 过滤器,执行一个过滤器会有返回个枚举值,即DENY,NEUTRAL,ACCEPT其中之 ...
- javaweb之Filter过滤器详解
快速入门 1.新建一个类,实现Filter接口 2.实现doFilter()方法,打印一句话,来证明能够进行拦截 3.在web.xml中进行配置(参照Servlet配置) 4.访问一个页面,看看能不能 ...
- web.xml 中的listener、 filter、servlet 加载顺序及其详解
在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是 ...
- logback配置详解3<filter>
logback 常用配置详解(三) <filter> <filter>: 过滤器,执行一个过滤器会有返回个枚举值,即DENY,NEUTRAL,ACCEPT其中之一.返回DENY ...
- 【转】logback logback.xml常用配置详解(三) <filter>
原创文章,转载请指明出处:http://aub.iteye.com/blog/1110008, 尊重他人即尊重自己 详细整理了logback常用配置, 不是官网手册的翻译版,而是使用总结,旨在更快更透 ...
- angular-ngSanitize模块-linky过滤器详解
本篇主要讲解angular中的linky这个过滤器.此过滤器依赖于ngSanitize模块. linky能找出文本中的链接,然后把它转换成html链接.什么意思,就是说,一段文本里有一个链接,但是这个 ...
随机推荐
- AQS: 什么是AQS?
AQS定义了一套多线程访问共享资源的同步器框架. 许多同步类实现都依赖于它,如常用的ReentrantLock/ReentrantReadWriterLock/CountDownLatch这些类里面都 ...
- 有关iOS热更新
iOS热更新的几篇文章,看完这几篇,自己集成一下.下面说一下我集成时遇到的问题. 这是原作者的JSPatch的讲解的文章:<JSPatch – 动态更新iOS APP>.<JSPat ...
- Java——Collection集合、迭代器、泛型
集合 ——集合就是java提供的一种容器,可以用来存储多个数据. 集合和数组的区别 数组的长度是固定的.集合的长度是可变的. 数组中存储的是同一类型的元素,可以存储基本数据类型值. 集合存储的都是对象 ...
- << 和>> 的计算公式
在java中,一个数左移n位,就是将这个数乘以2的n次方,右移就是将这个数除以2的n次方. 如: 8>>2 = 2 (8/2^2) 15 << 3 = 120 (15*(2 ...
- King of the Waves
You are organising a king of the hill tournament, the Buenos Aires Paddleboarding Competition (BAPC) ...
- 项目部署篇之二——linux下安装jdk1.8
1.下载jdk1.8 百度云下载后,直接通过xftp拖到你想放的目录下就行了,实在方便 链接:https://pan.baidu.com/s/1hQl0_3owT776lRO9mHSbXA 提取码:2 ...
- javascript 获取 sx:datetimepicker 的值
<div align="center"><sx:datetimepicker label="Start_Time" id="S ...
- MRP执行计划列表(禁用)
1.最直接的方法,推进方法 2.比较麻烦的方法
- 学习python-20191208(1)-Python Flask高级编程开发鱼书_第03章_数据与flask路由
视频01: 略...... ———————————————————————————————————————————————————————————— 视频02: 搜索需要外部数据源,也就是需要外部的A ...
- python3下scrapy爬虫(第十卷:scrapy数据存储进mysql)
上一卷中我将爬取的数据文件直接写入文本文件中,现在我将数据存储到mysql中,我依然用的是pymysql,这个很麻烦建表需要在外面建 这次代码只需要改变pipyline就行 来 现在看下结果: 对比发 ...