Filter in Servlet
Posted schhz208
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Filter in Servlet相关的知识,希望对你有一定的参考价值。
一、什么是Filter
过滤器(Filter)是可以转换请求或响应的标题和内容(或两者)的对象。过滤器不同于Web组件,因为过滤器本身通常不会创建响应。相反,过滤器提供的功能可以“附加”到任何类型的Web资源。因此,过滤器不应该对它作为过滤器的Web资源有任何依赖;这样,它可以由多个类型的web资源组成。
二、Filter可执行的主要任务
过滤器可以执行的主要任务如下。
- 查询请求并采取相应的行动。
-
阻止请求和响应对进一步传递。
-
修改请求头和数据。您可以通过提供自定义版本的请求来做到这一点。
-
修改响应头和数据。您可以通过提供响应的自定义版本来做到这一点。
-
与外部资源互动。
过滤器的应用包括身份验证、日志记录、图像转换、数据压缩、加密、标记流、XML转换等。
您可以将Web资源配置为按特定顺序由零、一个或多个筛选器链进行筛选。此链是在部署包含组件的Web应用程序时指定的,并在Web容器加载组件时实例化。
三、Filter如何工作
Filter也是在web.xml中另外一个常用的配置项,可以通过<filter>和<filter-mapping>组合来使用Filter。实际上Filter 可以完成与Servlet同样的工作,甚至比Servlet 使用起来更加灵活,因为它除了提供了request和response对象外,还提供了一个FilterChain对象,这个对象可以让我们更加灵活地控制请求的流转。下面看一下与Filter相关的类结构图,如图3-1所示。
图3-1 Filter相关的类结构图
在Tomcat容器中,FilterConfig 和FilterChain的实现类分别是ApplicationFilterConfig和ApplicationFilterChain,而Filter 的实现类由用户自定义,只要实现Filter 接口中定义的三个接口就行,这三个接口与在Servlet中的类似。只不过还有一个ApplicationFilterChain类,这个类可以将多个Filter串联起来,组成一个链,这个链与Jtty中的Handler链有异曲同工之妙。下面详细看一下Filter 类中的三个接口方法。
- init(FilterConfig):初始化接口,在用户自定义的Filter 初始化时被调用,它与Servlet的init 方法的作用是一样的,FilterConfig 与ServletConfig也类似,除了都能取到容器的环境类ServletContext 对象之外,还能获取在<filter>下配置的<init-param>参数值。
- doFilter ( ServletRequest, ServletResponse, FilterChain):在每个用户的请求进来时这个方法都会被调用,并在Servlet的service方法之前被调用。而FilterChain就代表当前的整个请求链,所以通过调用FilterChain.doFilter可以将请求继续传递下去。如果想拦截这个请求,可以不调用FilterChain.doFilter, 那么这个请求就直接返回了。所以Filter是一种责任链设计模式。
- destroy:当Filter 对象被销毁时,这个方法被调用。注意,当Web容器调用这个方法之后,容器会再调用一次doFilter方法。
Filter类的核心还是传递的FilterChain对象,这个对象保存了到最终Servlet对象的所有Filter对象,这些对象都保存ApplicationFilterChain对象的filters 数组中。在FiterChain链上每执行一个Filter 对象,数组的当前计数都会加1,直到计数等于数组的长度,当FilterChain上所有的Filter对象执行完成后,就会执行最终的Servlet。所以在Applicationitenchain对角山人持有Servlet对象的引用。图3-2是Filter对象的执行时序图。
图3-2 Filter执行时序图
Fiter 存在的意义就好比是你要去北京,它是你的目的地,但是提供一个机制让你在去的途中可以做一些拦截工作, 如可以将你的些行李包存放在某个 “存放处”,当你返回时你可以再从这个地方取回。总之它可以在你的途中增加一些东西,或者减少些东西。
四、Programming Filters
过滤API由Filter
, FilterChain
,和FilterConfig
中的接口。javax.servlet
包裹。通过实现Filter
接口。
使用@WebFilter
注释来定义Web应用程序中的筛选器。此注释是在类上指定的,并包含有关所声明的筛选器的元数据。带注释的筛选器必须指定至少一个URL模式。这是通过使用urlPatterns
或value
属性。所有其他属性都是可选的,具有默认设置。使用value
当注释中的唯一属性是URL模式时,请使用urlPatterns
属性时,也使用其他属性。
类注释为@WebFilter
注释必须实现javax.servlet.Filter
接口。
若要向筛选器添加配置数据,请指定initParams
属性的@WebFilter
注释这个initParams
属性包含@WebInitParam
注释下面的代码段定义了一个过滤器,并指定了一个初始化参数:
import javax.servlet.Filter;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
@WebFilter(filterName = "TimeOfDayFilter",
urlPatterns = {"/*"},
initParams = {
@WebInitParam(name = "mood", value = "awake")})
public class TimeOfDayFilter implements Filter {
...
中最重要的方法Filter
接口是doFilter
传递请求、响应和筛选链对象。此方法可以执行以下操作。
-
检查请求头。
-
如果筛选器希望修改请求头或数据,请自定义请求对象。
-
如果筛选器希望修改响应头或数据,则自定义响应对象。
-
调用筛选链中的下一个实体。如果当前过滤器是以目标Web组件或静态资源结尾的链中的最后一个过滤器,则下一个实体是链末尾的资源;否则,它就是WAR中配置的下一个过滤器。过滤器通过调用
doFilter
方法,传递被调用的请求和响应或它可能创建的包装版本。或者,过滤器可以选择通过不调用下一个实体来阻止请求。在后一种情况下,过滤器负责填充响应。 -
在调用链中的下一个过滤器后检查响应头。
-
抛出异常以指示处理中的错误。
除了doFilter之外,则必须实现init
和destroy
方法。这个init
方法由容器在实例化筛选器时调用。如果希望将初始化参数传递给筛选器,则可以从FilterConfig
对象传递给init
.
编写定制的请求和响应
过滤器可以通过多种方式修改请求或响应。例如,筛选器可以向请求添加属性,也可以在响应中插入数据。
修改响应的筛选器通常必须在将响应返回给客户端之前捕获响应。为此,您向生成响应的servlet传递一个备用流。备用流阻止servlet在完成时关闭原始响应流,并允许过滤器修改servlet的响应。
若要将此暂存流传递给servlet,筛选器将创建一个响应包装器,该响应包装器将重写getWriter
或getOutputStream
方法返回此暂存流。包装器被传递给doFilter
过滤链的方法。包装方法默认为调用包装请求或响应对象。
若要重写请求方法,请将请求包装在扩展ServletRequestWrapper
或HttpServletRequestWrapper
。若要重写响应方法,请将响应包装在扩展ServletResponseWrapper
或HttpServletResponseWrapper
.
指定过滤器映射
Web容器使用筛选器映射来决定如何将筛选器应用到Web资源。过滤器映射通过名称或URL模式将过滤器匹配到Web组件或Web资源。过滤器是按照筛选器映射出现在WAR的筛选映射列表中的顺序调用的。您可以使用NetBeansIDE或使用XML手工编写WAR的筛选器映射列表,从而在其部署描述符中指定筛选器映射列表。
如果要将每个请求记录到Web应用程序,则可以将点击计数器筛选器映射到URL模式/*
.
可以将筛选器映射到一个或多个Web资源,也可以将多个筛选器映射到Web资源。这在图4-1,其中过滤器F1映射到servlet S1、S2和S3;过滤器F2映射到Servlet S2;过滤器F3映射到servlet S1和S2。
图4-1 Filter到servlet映射
回想一下,筛选链是传递给doFilter
过滤器的方法。该链是通过滤波器映射间接形成的。链中过滤器的顺序与过滤器映射出现在Web应用程序部署描述符中的顺序相同。
当筛选器映射到Servlet S1时,web容器将调用doFilter
F1法这个doFilter
方法调用该链中的前面的筛选器调用s1的筛选链中的每个过滤器的方法。chain.doFilter
方法。因为S1的过滤器链包含过滤器f1和f3,所以f1调用chain.doFilter
调用doFilter
F3滤光片法。当F3‘sdoFilter
方法完成,控件返回到f1的doFilter
方法。
以上是关于Filter in Servlet的主要内容,如果未能解决你的问题,请参考以下文章
servlet,filter,listener,intercepter区别