Servlet过滤器的执行顺序

31
我发现了我的Web应用程序中的一个错误,让我不禁想了好一会儿才弄清楚发生了什么。(最终)在找到问题所在之前,我一直感到困惑。基本上,我在我的web.xml中定义了2个过滤器,并且这两个映射如下:
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <servlet-name>SpringMVCDispatcher</servlet-name>
</filter-mapping>

<filter-mapping>
    <filter-name>SpringFormMethodFilter</filter-name>
    <url-pattern>/administration/*</url-pattern>
</filter-mapping>

他们都是Spring MVC过滤器。我的问题是,尽管encodingFilter应该在任何其他东西读取之前将请求编码设置为UTF-8,但我得到的表单数据并未被解释为UTF-8。最终我注意到,虽然过滤器映射的顺序应该是它们链接的顺序,但表单方法过滤器在编码过滤器之前执行:

链中过滤器的顺序与Web应用程序部署描述符中出现的过滤器映射的顺序相同。

(来自Oracle

当我对两个映射使用相同的映射,即将其映射到一个Servlet而不是URL模式时,顺序得以恢复,一切都按预期工作:

<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <servlet-name>SpringMVCDispatcher</servlet-name>
</filter-mapping>

<filter-mapping>
    <filter-name>SpringFormMethodFilter</filter-name>
    <servlet-name>SpringMVCDispatcher</servlet-name>
</filter-mapping>

这是Servlet规范的一部分还是Tomcat的错误?有没有记录在案的文档,我需要提交错误报告吗?
我正在使用Java 7的Tomcat 7.0.39。
2个回答

48
当容器收到请求时,它首先查找所有与请求URI匹配的<url-pattern>的过滤器映射。这将成为过滤器链中的第一组过滤器。接下来,它查找所有与请求URI匹配的<servlet-name>的过滤器映射。这将成为过滤器链中的第二组过滤器。在两个集合中,过滤器按照在部署描述符(D.D.)中声明的顺序执行。
根据specs的规定:
容器在构建要应用于特定请求URI的过滤器链时使用的顺序如下:
  1. 首先,按照这些元素在部署描述符中出现的顺序,匹配<url-pattern>的过滤器映射。
  2. 接下来,按照这些元素在部署描述符中出现的顺序,匹配<servlet-name>的过滤器映射。

D.D. 是什么意思? - Grim
@PeterRader 部署描述符:web.xml - AllTooSir

-7
此外,您可以定义应用过滤器的顺序。这可以通过在web.xml中添加以下行来实现:
<absolute-ordering>
  <name>encodingFilter</name>
  <name>SpringFormMethodFilter</name>
</absolute-ordering>

请查看this以获取更多信息。


9
这是完全错误的,那个外部标签是用于片段而不是过滤器。 - user177800

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接