doFilter 调用了两次,预期的行为?

我正在学习Java EE servlet教程,并尝试了情绪示例。我注意到 doFilter 被调用了两次,一次 servlet 调用在链中,第二次不在。

我在TimeOfDayFilter.java和MoodServlet.java中添加了一些printlns来展示这一点。

TimeOfDayFilter.java:

    ...
    System.out.println("TimeOfDay before"); //added
    chain.doFilter(req, res);
    System.out.println("TimeOfDay after"); //added
    ...

MoodServlet.java:

    ...
    response.setContentType("text/html;charset=UTF-8");

    System.out.println("MoodServlet"); //added

    PrintWriter out = response.getWriter();
    ...

调用 servlet 时,玻璃鱼服务器 (3.1) 窗口的结果如下:

    INFO: mood was successfully deployed in 406 milliseconds.
    INFO: TimeOfDay before
    INFO: MoodServlet
    INFO: TimeOfDay after
    INFO: TimeOfDay before
    INFO: TimeOfDay after

这是预期的行为吗?如果是这样,额外呼叫的原因是什么?


答案 1
chain.doFilter(request,response);

这会将控件传递给与过滤器关联的 servlet。但是在执行相应的 servlet 之后,控件在上述行的末尾返回,并且执行当前 doFilter() 中的所有行。

如果要将控件永久传递给 servlet,并且不让它返回到过滤器,只需添加一个

return;

在当前筛选器中的 chain.doFilter(request,response) 行的末尾。


答案 2

该方法对每个请求调用一次。您可以在调用链中的其他筛选器之前执行一些代码,也可以在调用之后(按照筛选器链中指定的顺序,按照顺序)执行一些代码,如下所示:Filter.doFilterweb.xml filter-mapping

public MyFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response,
           FilterChain chain) 
           throws IOException, ServletException
    {
        codeToExecuteBeforeOtherFiltersInTheChain(request, response);

        chain.doFilter(request, response);

        codeToExecuteAfterOtherFiltersInTheChain(request, response);

    }
}

如果您的筛选器配置为调度和请求,则将为原始请求调用该方法一次,如果请求已转发,则将调用该方法一次:REQUESTFORWARDMyFilter.doFilter

使用文件配置过滤器映射:web.xml

...
<filter-mapping>
      <filter-name>MyFilter</filter-name>
      <url-pattern>/*</url-pattern>
      <dispatcher>REQUEST</dispatcher>
      <dispatcher>FORWARD</dispatcher>
</filter-mapping>
...

使用@WebFilter注释配置筛选器映射:

@WebFilter(urlPatterns = "/*", dispatcherTypes = {
    DispatcherType.REQUEST, DispatcherType.FORWARD
}) public MyFilter implements Filter {
    ...
}

为了能够检查请求是否已转发,您可以使用此处描述的请求属性:如何知道请求何时在 RequestWrapper 对象中转发

有关筛选器的详细信息,请参阅: https://docs.oracle.com/cd/B32110_01/web.1013/b28959/filters.htm


推荐