Filter

原文链接https://dotblogs.com.tw/alantsai/2013/10/10/servlet-filter


 

1.Filter基本结构

Filter就像是 Client 以及 Servlet之间的看门人,无论进出都要经过他。

Filter功能很强大,可以实现很多功能。比如:

记录有谁进出(log往来的request)、限制谁可以进入(未登录不能进入)、检查违禁物品(例如过滤掉sql injection)、出门时打上标签(例如给返回的图片做水印)

Filter可以有很多个,所以又称为Filter Chain,每一个Filter关注一个事情就ok

2.Filter的作用

在web开发中经常会有,跳转不同页面前判断用户是否登录的逻辑,当然这些都可以在Servlet中实现,但是如果有20个Servlet都需要加入这段逻辑,就显得有些冗余了。此时需要引出Servlet的看门人Filte。

Filter 翻译为过滤器 前面举得那个是否登录的例子就是一个“过滤”体现  除了单纯过滤(分发)之外,Filter还可以对request response内容进行修改

eg: 将所有进来的request response都是用UTF-8 编码 ,此时可以使用Filter来实现

 1      <filter>
 2         <filter-name>encodingFilter</filter-name>
 3         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
 4         <init-param>
 5             <param-name>encoding</param-name>
 6             <param-value>UTF-8</param-value>
 7         </init-param>
 8         <init-param>
 9             <param-name>forceEncoding</param-name>
10             <param-value>true</param-value>
11         </init-param>
12     </filter>
13     <filter-mapping>
14         <filter-name>encodingFilter</filter-name>
15         <url-pattern>/*</url-pattern>
16     </filter-mapping>

 3.Filter具体实现

javax.Servlet.Filter这个interface 有三个方法需要实现

1.public void init(FilterConfig config)

2.public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

3.public void destroy()

其中init destroy 方法都只会执行一次 目的是初始化和释放资源 而实际工作都在doFilter里面

doFilter比较特别的地方是FilterChain  FilterChain记录的是下一个关卡是谁

PS:这些Filter对象都保存在ApplicationFilterChain对象的数组中,在FilterChain链上每执行一个Filter对象,数组当前计数都会+1,直到计数等于数组长度。当FilterChain上所有的Filter对象执行完成后,就会执行最终的 Servlet

1 public void doFilter(ServletRequest request, ServletResponse, FilterChain chain)
2     ,throws ServletException, IOException
3 {
4     //這邊是在request進來做處理的地方
5     doFilter(request, response);
6     //这边我理解是response出来做处理的地方,这条链子的终点到
7        //Servlet,在回到这边未执行完的方法中,对response进行加工处理
8 }

有了看门人之后,需要通知程序在哪些“位置”(url-pattern),针对哪些“请求”(dispatcher),需要设置看门人。

 1 <filter>
 2     <filter-name>logFilter</filter-name>
 3     <filter-class>filter.LogFilter</filter-class>
 4     <init-param>
 5         <param-name>firstParam</param-name>
 6         <param-value>this is first init value</param-value>
 7     </init-param>
 8 </filter>
 9   
10 <filter-mapping>
11     <filter-name>logFilter</filter-name>
12     <url-pattern>*</url-pattern>
13     <dispatcher>REQUEST</dispatcher>
14 </filter-mapping>

 值得注意的是<dispatcher> 这个标签的内容表示在什么情况下Servlet需要执行这个Filter,默认是Request

  • REQUEST:当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。
  • INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
  • FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
  • ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

4.责任链模式在TomCat中的应用

  

 

其实在真正执行到TestFilter类之前,会经过很多Tomcat内部的类。顺带提一下其实Tomcat的容器设置也是责任链模式,注意被红色方框所圈中的类,从Engine到Host再到Context一直到Wrapper都是通过一个链传递请求。被绿色方框所圈中的地方有一个名为ApplicationFilterChain的类,ApplicationFilterChain类所扮演的就是抽象处理者角色,而具体处理者角色由各个Filter扮演。

 

posted @ 2017-07-05 22:34  丨核桃牛奶  阅读(175)  评论(0编辑  收藏  举报