过滤顺序和 web.xml 内容

Filter order and web.xml content

好了,开门见山: 我用 Eclipse 创建了两个过滤器(Filter1 和 Filter2)和一个 servlet(DisplayHeader) 来查看过滤器的执行顺序。 我使用 Tomcat 8.5 作为目标 运行time.

New/Dynamic 网络项目/ 上下文根 / 并检查了 "Generate web.xml delpoyment descriptor"

Filter1 在执行时打印 "I'm Filter 1",我 "linked" 将它打印到特定的 servlet "DisplayHeader"。 Filter2 它是孪生兄弟,有 2 个而不是 1 个。 DisplayHeader servlet 映射到 /DisplayHeader。

为清楚起见,下面是 Filter1 代码

import java.io.IOException;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;

@WebFilter(
        urlPatterns = {"/Filter1"}, 
        servletNames = {"DisplayHeader"}
        )
public class Filter1 implements Filter {

    /**
     * Default constructor. 
     */
    public Filter1() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        // place your code here
        System.out.println("I'm Filter 1");

        // pass the request along the filter chain
        chain.doFilter(request, response);
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }

}

好吧,当我 运行 Tomcat (Tomcat v8.5) 上的 servlet 时,它会打印

I'm Filter 1
I'm Filter 2

也就是说Filter1先于Filter2执行。

我读到过滤器的执行顺序来自 web.xml 文件中的映射顺序, 所以我希望在 web.xml 文件的某处找到类似

的内容
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/DisplayHeader</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>Filter2</filter-name>
<url-pattern>/DisplayHeader</url-pattern>
</filter-mapping>

我应该按顺序颠倒...

问题是:当我打开我项目的 web.xml(从项目资源管理器,见下图)文件时,我只看到这个:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>SetFilterOrder</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

web.xml location in the explorer

我只是缺少正确的 web.xml 文件路径还是这个 web.xml 是使用 "Generate web.xml delpoyment descriptor" 选项的结果?

根据我的阅读,Servlet 3.0 似乎没有提供通过注释定义顺序的方法。因此,要定义顺序,您必须使用 web.xml。它可能使用的顺序可能是按字母顺序排列的,也可能只是运气不好,classes 在进行注释扫描时首先出现。您可以测试一下是否弄乱了过滤器名称或过滤器 class 名称。最终你不能依赖这个。可以肯定的是,您似乎必须恢复到 web.xml.

参考文献:
How to define servlet filter order of execution using annotations in WAR

http://www.concretepage.com/java-ee/jsp-servlet/how-to-use-filter-in-servlet-3-with-webfilter-annotation

http://javabycode.com/java-frameworks/servlet-jsp/filter-servlet-3-using-webfilter-annotation-example.html

根据我的经验,过滤器链从根开始向上运行。

假设你有:

domain.com/loggedInArea/UserProfile/Address.jsp. 

如果每个级别都有一个过滤器,它们将从 "shortest" URL 开始执行到 "longest":

@WebFilter("/*")
@WebFilter("/loggedInArea/*")
@WebFilter("/loggedInArea/UserProfile/*")
@WebFilter("/loggedInArea/UserProfile/Address.jsp")

您不能真正使用 URL 过滤器通配符,因为您可以在搜索文件名等方面使用它们。所以,你可以搜索

Addr*.jsp

但您不能使用它来指定 WebFilter URL

如果我没理解错的话,你提到的例子只是你为了练习 WebFilters 而创建的东西 - 绝对没问题 - 而不是你正在从事的项目的要求。我想不出一个现实生活中的例子,你需要确定过滤器的执行顺序而不是 URL 级别。

你不能

@WebFilter("/loggedInArea/UserProfile/Address.*p")
@WebFilter("/loggedInArea/UserProfile/Addr*sp")

因为您将不得不使用特定的文件名,并且它们将相互排斥。

如果您有两个具有相同 URL

的不同过滤器
@WebFilter("/loggedInArea/UserProfile/*")
@WebFilter("/loggedInArea/UserProfile/*")

(如果你有这个,Tomcat 甚至可能拒绝启动,不确定)那么它肯定应该被压缩到一个过滤器中,你可以从中控制流量。