WEB-INF/web.xml 和 conf/web.xml 中定义的 servlet 过滤器的实际执行顺序是啥

Posted

技术标签:

【中文标题】WEB-INF/web.xml 和 conf/web.xml 中定义的 servlet 过滤器的实际执行顺序是啥【英文标题】:What is the actual order of execution for servlet filters defined in WEB-INF/web.xml and conf/web.xmlWEB-INF/web.xml 和 conf/web.xml 中定义的 servlet 过滤器的实际执行顺序是什么 【发布时间】:2015-09-22 08:59:06 【问题描述】:

根据我的理解,过滤器执行的顺序是它们在 web.xml 中为相同的 url-mapping 定义的顺序。但是,如果我们为跨容器的 web.xml 和单个应用程序的 web.xml 的相同 url 映射定义了多个过滤器,我找不到任何参考。

我的假设是,由于应用程序是作为容器的一部分部署的,比如说 tomcat,它有自己的 web.xml,针对每个此类部署的应用程序的任何请求都必须通过 tomcat 中定义的过滤器链/conf/web.xml 在通过应用程序过滤器之前。但是我的理解是错误的

我有一个简单的 web 应用程序,在 web.xml 中定义了两个过滤器,如下所示

<filter>
    <filter-name>AppFilterOne</filter-name>
    <filter-class>com.test.filters.AppFilterOne</filter-class>
</filter>
<filter>
     <filter-name>AppFilterTwo</filter-name>
     <filter-class>com.test.filters.AppFilterTwo</filter-class>
</filter>
<filter-mapping>
     <filter-name>AppFilterOne</filter-name>
     <url-pattern>/*</url-pattern>
</filter-mapping>

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

没有任何进一步的改变,如果我点击我的网址http://localhost:8080/myapp,我会看到 AppFilterOne 和 AppFilterTwo 按该顺序被点击。

现在,我在我的 tomcat/conf/web.xml 中添加了两个过滤器(我的 tomcat 版本是 7.0.27 并支持 servlet 3.0)

<filter>
    <filter-name>TomWebFilterOne</filter-name>
    <filter-class>com.test.filter.TomWebFilterOne</filter-class>
</filter>

 <filter>
    <filter-name>TomWebFilterTwo</filter-name>
        <filter-class>com.test.filter.TomWebFilterTwo</filter-class>
  </filter>

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

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

现在,如果我访问http://localhost:8080/myapp,过滤器按以下顺序执行 AppFilterOne 应用过滤器二 TomWebFilterOne TomWebFilterTwo

我最初的假设是,TomWebFilters 将首先拦截,然后是应用程序特定的过滤器。

如果我看到的结果实际上是正确的并且这就是过滤器的工作方式,有没有办法可以影响过滤器的执行顺序。我听说过,但不确定,这是否是正确的方法。

我的实际问题有一点背景: 我们在 tomcat 7X 实例的不同虚拟机中部署了一堆 Web 应用程序。这些 Web 应用程序中的每一个都有一个审计过滤器,用于审计和记录每个传入的请求。但是,在 tomcat /conf/web.xml 中定义了一个过滤器以支持 NTLM 身份验证(JCIFS 风格)。由于这种设置,每个进来的请求实际上都会被记录下来(作为审计过滤器的一部分),然后针对 NTLM 进行过滤。我们希望 NTLM 先发生,然后再发生其他任何事情。

有几种方法,我在这里考虑 A) 我们可能需要将该过滤器定义为每个应用程序中的第一个过滤器,而不是在 tomcat/conf/web.xml 中定义。 B) 让 NTLM 过滤器在请求中设置一个属性,说明 NTLM 进程的状态,我们的审计过滤器将检查两次(即两个 401 HTTP 状态代码),然后返回。

我对这两种方法都不是特别满意,因此想知道可以做什么

谢谢

【问题讨论】:

【参考方案1】:

为了解决我最初的审计日志问题,我没有在应用程序 web.xml 中使用过滤器,而是为此使用了 AOP。它似乎工作正常。但是我仍然很想知道,是否有一种标准的方式来影响在 WEB-INF/web.xml 和 conf/web.xml 之间声明的过滤器序列

【讨论】:

以上是关于WEB-INF/web.xml 和 conf/web.xml 中定义的 servlet 过滤器的实际执行顺序是啥的主要内容,如果未能解决你的问题,请参考以下文章

J2EE:为啥getServletContext().getResourceAsStream("/WEB-INF/web.xml");读取不到呢?

java.lang.IllegalArgument,Parse error in application web.xml file at jndi:/localhost/WEB-INF/web.xml

我在web-inf下有一个xml配置文件 在一个java类中怎么获得这个配置文件的路径?大神指教

[RoarCTF 2019]Easy Java

禁用 Maven 警告消息 - “选定的战争文件包括将被忽略的 WEB-INF/web.xml”

[WARNING] Warning: selected war files include a WEB-INF/web.xml which will be ignored (webxml attrib