ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Filter执行顺序

2022-07-21 10:00:48  阅读:85  来源: 互联网

标签:xml web 顺序 Filter 执行 filter characterEncodingFilter


web.xml情况下的执行顺序

在使用web.xml进行配置的情况下,filter的执行顺序很容易确定,以下是Servlet3官方定义中的描述:

  1. 与请求相匹配的,filter-mapping元素中包含url-pattern的Filter,将以它们在web.xml中出现的顺序被添加到过滤器链中
  2. 与请求相匹配的,filter-mapping元素中包含一个servlet-name的Filter,将被添加到过滤器链中<url-pattern>匹配的所有Filter后面,也是以它们在web.xml中出现的顺序
  3. 过滤器链中的最后一个项目总是原始请求资源

url-pattern的测试

下面我们有两个Filter,authFilter用于校验用户是否登录,并将它带到合适的位置,characterEncodingFilter将使用合适的编码解析前端请求、编码后端给前端返回的响应。我们希望任何时候,characterEncodingFilter总能排在最前面,因为我们希望若authFitler中也用到前端的请求参数、或返回一些内容给前端时,它的编码也是正确的

下面的定义中,两个filter-mapping元素都满足官方定义中的第一条,而characterEncodingFitler定义在前,所以characterEncodingFilter先执行。

<filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>top.yudoge.webreview2.filters.CharacterEncodingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>authFilter</filter-name>
    <filter-class>top.yudoge.webreview2.filters.AuthFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>authFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

前端进行请求:

img

官方定义中说,顺序的标准是由filter-mapping元素出现的先后定义,我们试试把filter元素以相反的顺序放置,看看会不会受到影响,按官方定义来说应该是不会。

<filter>
    <filter-name>authFilter</filter-name>
    <filter-class>top.yudoge.webreview2.filters.AuthFilter</filter-class>
</filter>
<filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>top.yudoge.webreview2.filters.CharacterEncodingFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>authFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

前端访问后的结果,确实不会:

img

servlet-name的测试

我从没这样用过Filter,按官方的说法,这是给指定的Servlet添加Filter,所有最终由这个Servlet处理的请求都会经过这个Filter。

现在,我们在上面的基础上,向名为loginServlet的Servlet添加一个Filter,注意,这个Filter的filter-mapping元素在web.xml的位置在之前的两个之上:

<filter>
    <filter-name>testFilterOne</filter-name>
    <filter-class>top.yudoge.webreview2.filters.TestFilterOne</filter-class>
</filter>
<filter-mapping>
    <filter-name>testFilterOne</filter-name>
    <servlet-name>loginServlet</servlet-name>
</filter-mapping>

现在我们访问loginServlet,按照官方的说法,应该是servlet-name所匹配的Filter的优先级不如由url-pattern所匹配的Filter,所以,它应该在最后:

img

testFilterOne上面添加testFilterTwo

<filter>
    <filter-name>testFilterTwo</filter-name>
    <filter-class>top.yudoge.webreview2.filters.TestFilterTwo</filter-class>
</filter>
<filter-mapping>
    <filter-name>testFilterTwo</filter-name>
    <servlet-name>loginServlet</servlet-name>
</filter-mapping>

<filter>
    <filter-name>testFilterOne</filter-name>
    <filter-class>top.yudoge.webreview2.filters.TestFilterOne</filter-class>
</filter>
<filter-mapping>
    <filter-name>testFilterOne</filter-name>
    <servlet-name>loginServlet</servlet-name>
</filter-mapping>

位置在上的testFilterTwo在另一个之前被触发:

img

下面调整filter-mapping的顺序,让testFilterTwo在下面,结果是它们被调用的顺序也发生了变化:

img

<filter-mapping>中具有多个匹配方式的情况

下面是官方定义中的一个例子

img

对于这种定义,容器必须将它展开,所以它等价于:

img

web.xml情况下的总结

<url-pattern>匹配的Filter的调用顺序由<filter-mapping>元素在web.xml中的位置决定,靠上的先被调用。

<servlet-name>匹配的Filter总是在所有由<url-pattern>匹配的Filter调用之后被调用,它们之间的顺序也是由它们在web.xml中的位置决定的。

<filter-mapping>中有多个匹配方式,这时相当于展开的多个<filter-mapping>的顺序情况。

注解情况下的执行顺序

Servlet3.0定义中并没有对注解情况下的Filter执行顺序,也就是说它的顺序由实现决定,网上有人查看Tomcat的源码后发现是按照简单类名的字典序排序的。

现在,删除web.xml中所有filter相关的定义,在CharacterEncodingFilterAuthFilter上添加@WebFilter注解:

img

结果,是AuthFilter在前被调用:

img

修改它们的类名为Filter01_CharacterEncodingFilterFilter02_AuthFilter,如果是按照类名的字典序,那么这次应该是CharacterEncodingFilter先被调用。

结果确实是这样,CharacterEncodingFilter被先调用了:

img

但是本着尽量不要写出与特定实现相关的代码的原则,这种代码还是不要写。而且修改后的类名让人很摸不着头脑。

使用注解搭配web.xml

虽然确实,在@WebFilter中添加一个类似order的属性在技术上没什么难的,但是关键的问题是,这样的意义很有限。

考虑使用第三方框架的情况,第三方框架为了实现功能往往要向FilterChain中注入一批Filter,框架往往希望它的Filter总是最先被调用。但是框架编写的时候不了解你的代码中Filter如何定义,你使用框架时也不了解框架的代码中Filter如何定义,这些问题导致无论是你还是框架开发者都难以使用注解的order属性来定义具体的执行顺序。可能正是因为这个考虑,Servlet3.0标准中没有在注解里提供一个order属性,牺牲了在不使用其它框架时的易用性。

不过,我们可以通过使用注解+web.xml共同描述一个Filter,使用注解让容器可以自动扫描到一个Filter,使用web.xml的<filter-mapping>元素描述顺序

两个Filter类上的注解:

@WebFilter(filterName = "characterEncodingFilter")
@WebFilter(filterName = "authFilter")

web.xml中,将characterEncodingFilter<filter-mapping>注解注册在前:

<filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>authFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

结果:

img

标签:xml,web,顺序,Filter,执行,filter,characterEncodingFilter
来源: https://www.cnblogs.com/lilpig/p/16500861.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有