Filter(过滤器)简介:
Filter 的基本功能是对 Servlet 容器调用 Servlet 的过程进行拦截,从而在 Servlet 进行响应处理的前后实现一些特殊的功能。在
Servlet API 中定义了三个接口类来开供开发人员编写 Filter 程序:Filter, FilterChain, FilterConfig。Filter 程序是一个实现了 Filter
接口的 Java 类,与 Servlet 程序相似,它由 Servlet 容器进行调用和执行Filter 程序需要在web.xml 文件中进行注册和设置它所能拦截
的资源:Filter 程序可以拦截 Jsp, Servlet, 静态图片文件和静态 html 文件。
Filter 的基本工作原理:
当在 web.xml 中注册了一个 Filter 来对某个 Servlet 程序进行拦截处理时,这个 Filter 就成了 Servlet 容器与该 Servlet 程序的
通信线路上的一道关卡,该 Filter 可以对 Servlet 容器发送给 Servlet 程序的请求和 Servlet 程序回送给 Servlet 容器的相应进行拦
截,可以决定是否将请求继续传递给 Servlet 程序,以及对请求和相应信息是否进行修改在一个 web 应用程序中可以注册多个Filter 程
序,每个 Filter 程序都可以对一个或一组 Servlet 程序进行拦截。若有多个 Filter 程序对某个 Servlet 程序的访问过程进行拦截,当针
对该 Servlet 的访问请求到达时,web 容器将把这多个 Filter 程序组合成一个 Filter 链(过滤器链)。Filter 链中各个 Filter 的拦截顺序
与它们在应用程序的 web.xml 中映射的顺序一致。
Filter 接口:
init(FilterConfig filterConfig)throws ServletException:在 web 应用程序启动时,web 服务器将根据 web.xml 文件中的配
置信息来创建每个注册的 Filter 实例对象,并将其保存在服务器的内存中。Web容器创建 Filter 对象实例后,将立即调用该 Filter 对象的
init 方法。Init 方法在 Filter 生命周期中仅执行一次,web 容器在调用 init 方法时,会传递一个包含 Filter 的配置和运行环境的
FilterConfig 对象(FilterConfig的用法和ServletConfig类似)。利用FilterConfig对象可以得到ServletContext对象,以及部署描述符中
配置的过滤器的初始化参数。在这个方法中,可以抛出ServletException异常,通知容器该过滤器不能正常工作。
destroy(): 在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用
的资源。
与开发Servlet不同的是,Filter接口并没有相应的实现类可供继承,要开发过滤器,只能直接实现Filter接口。
doFilter(ServletRequest request,ServletResponse response, FilterChain chain) throws
java.io.IOException,ServletException:
doFilter()方法类似于Servlet接口的service()方法。当客户端请求目标资源的时候,容器就会调用与这个目标资源相关联的过滤器的
doFilter()方法。其中参数 request, response 为 web 容器或 Filter 链的上一个 Filter 传递过来的请求和相应对象;参数 chain 为代
表当前 Filter 链的对象,在特定的操作完成后,可以在当前 Filter 对象的 doFilter 方法内部需要调用 FilterChain 对象的
chain.doFilter(request,response)方法才能把请求交付给 Filter 链中的下一个 Filter 或者目标 Servlet 程序去处理,也可以直接向客
户端返回响应信息,或者利用RequestDispatcher的forward()和include()方法,以及 HttpServletResponse的sendRedirect()方法
将请求转向到其他资源。这个方法的请求和响应参数的类型是 ServletRequest和ServletResponse,也就是说,过滤器的使用并不依赖
于具体的协议。
FilterChain 接口:
FilterChain接口:代表当前 Filter 链的对象。由容器实现,容器将其实例作为参数传入过滤器对象的doFilter()方法中。过滤器对象使
用FilterChain对象调用过滤器链中的下一个过滤器,如果该过滤器是链中最后一个过滤器,那么将调用目标资源。
doFilter(ServletRequest request,ServletResponse response)throws java.io.IOException:调用该方法将使过滤器链中的下一
个过滤器被调用。如果是最后一个过滤器,会调用目标资源。 在实现一个过滤器后,需要在 web.xml 中进行注册和设置它所能拦截的资
源。这可以通过<filter>和<filter-mapping>元素来完成的。
其配置方式和servlet非常类似,下面是具体的配置代码:
<filter> <filter-name>myFilterConfig</filter-name> <filter-class>com.myfilter.MyFilterConfig</filter-class> <!-- 配置当前 Filter 的初始化参数 --> <init-param> <param-name>username</param-name> <param-value>admin</param-value> </init-param> <init-param> <param-name>password</param-name> <param-value>admin</param-value> </init-param> </filter> <filter-mapping> <filter-name>myFilterConfig</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
/* 表示所有的url都需要被这个过滤器所过滤
在同一个 web.xml 文件中可以为同一个 Filter 设置多个映射。若一个 Filter 链中多次出现了同一个 Filter 程序,这个 Filter 程序
的拦截处理过程将被多次执行。
Filter的典型应用1:使浏览器不缓存页面的过滤器
有 3 个 HTTP 响应头字段都可以禁止浏览器缓存当前页面,它们在 Servlet 中的示例代码如下:
response.setDateHeader("Expires",-1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma","no-cache");
并不是所有的浏览器都能完全支持上面的三个响应头,因此最好是同时使用上面的三个响应头
典型应用2 :字符编码的过滤器
通过配置参数encoding指明使用何种字符编码,以处理Html Form请求参数的中文问题
具体的实例代码如下:
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { arg0.setCharacterEncoding(“UTF-8”); arg2.doFilter(arg0, arg1); }