Filter详解
转自 http://blog.csdn.net/yudaoai/article/details/4231333
filter功能.它使用户可以改变一个 request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开 servlet时处理response.换种说法,filter其实是一个”servlet chaining”(servlet 链).
一个filter 包括:
1. 在servlet被调用之前截获;
2. 在servlet被调用之前检查servlet request;
3. 根据需要修改request头和request数据;
4. 根据需要修改response头和response数据;
5. 在servlet被调用之后截获.
通俗点说法filter相当于加油站,request是条路,response是条路,目的地是servlet,这个加油站设在什么地方对什么数据操作可以由你来控制。
一些需要过滤器的情况:
(1)认证Filter
(2)日志和审核Filter
(3)图片转换Filter
(4)数据压缩Filter
(5)密码Filter
(6)令牌Filter
(7)触发资源访问事件的Filter
(8)XSLT Filter
(9)媒体类型链Filter
1.批量设置请求编码
为了避免提交数据的中文乱码问题,需要在每次使用请求之前设置request.setCharacterEncoding("gb2312")编码格式,麻烦。Filter可以批量拦截修改servlet的请求和响应。
我们编写一个EncodingFilter.java,来批量设置请求编码。
public class EncodingFilter implements Filter {
public void init(FilterConfig config) throws ServletException {}
public void destroy() {}
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
request.setCharacterEncoding("gb2312");
chain.doFilter(request, response);
}
}
在此EncodingFilter实现了Filter接口,Filter接口中定义的三个方法都要在EncodingFilter中实现,其中doFilter()的代码实现主要的功能:
为请求设置gb2312编码并执行chain.doFilter()继续下面的操作。
转换成对应HttpServletRequest和HttpServletResponse才能进行下面的session操作和页面重定向。
与servlet相似,为了让filter发挥作用还需要在web.xml进行配置。
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>sam.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
filter标签部分定义使用的过滤器,filter-mapping标签告诉服务器把哪些请求交给过滤器处理。这里的/*表示所有请求,/表示根路径,*(星号)代表所有请求,加在一起就变成了根路径下的所有请求。
这样,所有的请求都会先被EncodingFilter拦截,并在请求里设置上指定的gb2312编码。
2.用filter控制用户访问权限
出于信息安全和其他一些原因的考虑,项目中的一些页面要求用户满足了一定条件之后才能访问让用户输入帐号和密码,如果输入的信息正确就在session里做一个成功的标记,这里的成功标志就是session中的username有值;
其后在请求保密信息的时候判断session中是否有已经登录成功的标记,存在则可以访问,不存在则禁止访问。
假设我们要保护的页面是admin/index.jsp
编写SecurityFilter.java,控制用户访问权限
public class SecurityFilter implements Filter {
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
HttpSession session = req.getSession();
if (session.getAttribute("username") != null) {
chain.doFilter(request, response);
} else {
res.sendRedirect("../failure.jsp");
}
}
web.xml进行如下配置
<filter>
<filter-name>SecurityFilter</filter-name>
<filter-class>sam.SecurityFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SecurityFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
定义SecurityFilter过滤器,让它过滤匹配/admin/*的所有请求,/admin/路径下的所有请求都会接受SecurityFilter的检查
因为Filter本来设计成为多种协议服务,http协议仅仅是其中一种,将ServletRequest和ServletResponse转换成HttpServletRequest和HttpServletResponse才能进行下面的session操作和页面重定向。
得到了http请求之后,可以获得请求对应的session,判断session中的username变量是否为null,如果不为null,说明用户已经登录,就可以调用doFilter继续请求访问的资源。如果为null,说明用户还没有登录,禁止用户访问,并使用页面重定向跳转到failure.jsp页面显示提示信息。
因为/failure.jsp的位置在/admin/目录的上一级,所以加上两个点才能正确跳转到failure.jsp,两个点(..)代表当前路径的上一级路径。
3.日志和审核Filter
public class LoggingFilter implements Filter {
private FilterConfig filterConfig = null;
public void init(FilterConfig config) throws ServletException {
this.filterConfig = config;
}
//下面是向服务器控制台输出log,这里做的是演示,更多的是使用log4j
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
String address = request.getRemoteAddr();
filterConfig.getServletContext().log("User IP: " + address);
chain.doFilter(request, response);
}
public void destroy() {
}
}
web.xml配置
<filter>
<filter-name>LoggingFilter</filter-name>
<filter-class>samjava.filter.LoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoggingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
4.filter所谓的特性
请求映射filter-mapping和servlet-mapping都是将对应的filter或servlet映射到某个url-pattern上,当客户发起某一请求时,服务器先将此请求与web.xml中定义的所有url-pattern进行匹配,然后执行匹配通过的filter和servlet。
你可以使用三种方式定义url-pattern。
直接映射一个请求。
<servlet-mapping>
<servlet-name>TestServlet</servlet-name>
<url-pattern>/TestServlet</url-pattern>
</servlet-mapping>
映射一个路径下的所有请求。
<servlet-mapping>
<servlet-name>EncodingFilter</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
需要注意的是,这种写法必须以/开头,写成与绝对路径的形式,即便是映射所有请求也要写成/*,不能简化成*。
映射结尾相同的一类请求。
<servlet-mapping>
<servlet-name>ControllerServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
需要注意的是,这种请求映射就不能指定某一路径了,它必须是以星号(*)开始字母结尾,不能写成/*.do的形式。
5.过滤链
我们使用了两个过滤器,EncodingFilter负责设置编码,SecurityFilter负责控制权限,那这两个过滤器是怎么起作用的呢?
所有的奥秘就在Filter中的FilterChain中。服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的doFilter()方法。执行的顺序就如上图所示,执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的chain.doFilter()之后的代码,最后返回响应。
代码执行顺序是:
(1)执行EncodingFilter.doFilter()中chain.doFilter()之前的部分:request.setCharacterEncoding("gb2312");
(2)执行SecurityFilter.doFilter()中chain.doFilter()之前的部分:判断用户是否已登录
(3)如果用户已登录,则访问请求的资源:/admin/index.jsp
(4)如果用户未登录,则页面重定向到:/failure.jsp
(5)执行SecurityFilter.doFilter()中chain.doFilter()之后的部分;
(6)执行EncodingFilter.doFilter()中chain.doFilter()之后的部分;
说的简单点就是filter将按照在web.xml文件中的声明顺序调用。
过滤链的好处是,执行过程中任何时候都可以打断,只要不执行chain.doFilter()就不会再执行后面的过滤器和请求的内容。
要特别注意过滤链的执行顺序问题,像EncodingFilter就一定要放在所有Filter之前(在web.xml文件中),这样才能确保在使用请求中的数据前设置正确的编码。
6.filter的详细配置
我们已经了解了filter的基本用法,还有一些细节配置在特殊情况下起作用。
在servlet-2.3中,Filter会过滤一切请求,包括服务器内部使用forward转发请求和<%@ include file="/index.jsp"%>的情况。
到了servlet-2.4中Filter默认下只拦截外部提交的请求,forward和include这些内部转发都不会被过滤,但是有时候我们需要forward的时候也用到Filter,这样就需要如下配置。
<filter>
<filter-name>TestFilter</filtername>
<filter-class>sam.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filtername>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>EXCEPTION</dispatcher>
</filter-mapping>
这样TestFilter就会过滤所有状态下的请求。如果我们没有进行设置,默认使用的就是REQUEST。而EXCEPTION是在isErrorPage="true"的情况下出现的,这个用处不多,看一下即可。
这里FORWARD是解决request.getDispatcher("index.jsp").forward(request, response);无法触发Filter的关键,配置上这个以后再进行forward的时候就可以触发过滤器了。
Filter详解的更多相关文章
- css filter详解
css filter详解 filter 属性详解 属性 名称 类型 说明 grayscale 灰度 值为数值 取值范围从0到1的小数(包括0和1) sepia 褐色 值为数值 取值范围从0到1的小数( ...
- Spring Security Filter详解
Spring Security Filter详解 汇总 Filter 作用 DelegatingFilterProxy Spring Security基于这个Filter建立拦截机制 Abstract ...
- java web之Filter详解
java web之Filter详解 2012-10-20 0 个评论 作者:chenshufei2 收藏 我要投稿 .概念: Filter也称之为过滤器,它是Servlet技术中比较激动人心的技术,W ...
- Zuul之Filter详解
Zuul详解 官方文档:https://github.com/Netflix/zuul/wiki/How-it-Works Zuul的中心是一系列过滤器,能够在HTTP请求和响应的路由过程中执行一系列 ...
- Servlet之Filter详解
参考文献:http://www.cnblogs.com/zlbx/p/4888312.html Filter,过滤器,顾名思义,即是对数据等的过滤,预处理过程.为什么要引入过滤器呢?在平常访问网站的时 ...
- CSS3 Filter详解(改变模糊度 亮度 透明度等方法)
CSS3 Filter(滤镜)属性提供了提供模糊和改变元素颜色的功能.CSS3 Fitler 常用于调整图像的渲染.背景或边框显示效果. -webkit-filter是css3的一个属性,Webkit ...
- bloom filter 详解[转]
Bloom Filter概念和原理 焦萌 2007年1月27日 Bloom Filter是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.Bloom ...
- 布隆过滤器(Bloom Filter)详解——基于多hash的概率查找思想
转自:http://www.cnblogs.com/haippy/archive/2012/07/13/2590351.html 布隆过滤器[1](Bloom Filter)是由布隆(Burton ...
- django中的filter详解
filter (数据过滤) 我们很少会一次性从数据库中取出所有的数据:通常都只针对一部分数据进行操作. 在Django API中,我们可以使用`` filter()`` 方法对数据进行过滤: > ...
- angularjs filter 详解
系统的学习了一下angularjs,发现angularjs的有些思想根php的模块smarty很像,例如数据绑定,filter.如果对smarty比较熟悉的话,学习angularjs会比较容易一点.这 ...
随机推荐
- SettingsJDK
迁移时间:2017年5月20日23:38:40 Author:Marydon 1.双击安装,更改安装路径为D:\ProgramFiles\Java\jdk1.7.0_55: 注意事项: 1.1 将 ...
- 〖Linux〗Ubuntu13.10,配置tftp服务器
前言,配置了好久没有发现老是出问题tftp: server error: (2) Access violation,一般侦测之后... 1. 安装软件包:apt-getsudo apt-get ins ...
- 〖Linux〗使用gsoap搭建web server(C)
1. gsoap的好处就不用说了:百度百科 2. gsoap的下载地址:项目地址,目前我使用的是2.8.15版本 3. 开发环境:Ubuntu13.10 4. 具体操作步骤(以简单相加为例): 1) ...
- Android网络开发之Socket通信
HTTP通信中Client发送的每次请求都需要Server回送响应,在请求结束后,Client会主动释放连接.从建立连接到隔壁连接的过程成为一次连接.要保持Client程序的在线状态,需要不断地向Se ...
- 深入PHP内核之数组
定义: PHP 中的数组实际上是一个有序映射.映射是一种把 values 关联到 keys 的类型.此类型在很多方面做了优化,因此可以把它当成真正的数组,或列表(向量),散列表(是映射的一种实现),字 ...
- Total Commander:文件管理工具,共享软件
http://xbeta.info/tc/ Total Commander V8.0:文件管理工具,共享软件,适用于Windows® 95/98/ME/NT/2000/XP/Vista/7 和 Win ...
- C# 调节图片亮度
原文地址:https://www.cnblogs.com/wjr408/p/6727118.html 昨天去客户那里测试,需求才开始,所以很简单,就是测一下能不能接受到视频或图片,然后保存下来,现场客 ...
- 西邮Linux兴趣小组纳新笔试试题
下面是西邮Linux小组今年纳新的笔试试题 1. 下面这个程序的输出结果是什么? int main() { int a = (1, 2); printf(“a = %d\n”, a); return ...
- 《TCP/IP具体解释卷2:实现》笔记--选路请求和选路消息
内核的各种协议并不直接使用前面提供的函数来訪问选路树,而是调用几个函数:rtalloc和rtallocl是完毕路由表查询的两个 函数:rtrequest函数用于加入和删除路由表项:另外大多数接口在接口 ...
- Python hypot() 函数
描述 hypot() 返回欧几里德范数 sqrt(x*x + y*y). 语法 以下是 hypot() 方法的语法: import math math.hypot(x, y) 注意:hypot()是不 ...