在Filter.doFilter方法中,chain.doFilter是做什么的?

46
在一个 Filter.doFilter 方法中,我调用了 chain.doFilter
在一个 doFilter 中调用 doFilter 是什么意思?这不是递归调用吗?

1
http://java.sun.com/products/servlet/Filters.html - Fortega
7个回答

61
Servlet过滤器是责任链设计模式的一种实现。
所有过滤器都被链接在一起(按照它们在web.xml中定义的顺序)。 chain.doFilter() 继续到链中的下一个元素。 链的最后一个元素是目标资源/Servlet。

嗨@Bozho,我可以在doFilter方法中添加另一个filter.doFilter()过滤器吗? - Helen

15

它调用chain对象的doFilter方法,而不是自身,因此不会发生递归。

名称chain表明您有一系列过滤器,每个过滤器都要进行一些处理,然后传递给序列中的下一个过滤器,因此每个对象都有一个chain成员指向序列中的下一个过滤器,在该过滤器执行自己的处理后被调用。序列中的最后一个过滤器可能会将chain值设置为null,或者它自己知道它是序列中的最后一个。


3

没有你所说的任何代码,我只能假设你是指:

class Filter implements FilterAPI {
  private FilterAPI chain;
  FilterAPI(FilterAPI chain) { this.chain = chain; }
  @override void doFilter (Set setToFilter) {
    // do some filtering on setToFilter
    chain.doFilter(setToFilter);
  }
}

如果是这种情况,那么你并没有递归调用任何东西,而是在不同的对象上调用doFilter()。正如另一个答案中所提到的那样,这是众所周知的“责任链”设计模式。


1
这似乎是C#,但这篇帖子标记为Java。然而,答案仍然是正确的。 - gbtimmon
我相信上面是有效的Java代码?不过我只是修正了构造函数的名称... - Paul Wagland
可能是因为我从未在Java中看到过FilterAPI接口,只看到了java.servlet.Filter,所以感到困惑。也许这只是我的无知。FilterAPI是从哪里来的? - gbtimmon
1
FilterAPI只是一个虚构的名称... 过滤器的API ;-) - Paul Wagland

2

在内部,它会调用过滤器链中下一个过滤器的doFilter方法,当链结束时,它会调用目标servlet。


1
通过调用chain.doFilter,您将请求/响应交给过滤器链中的下一个过滤器。如果您不调用它,则不会执行下一个过滤器(可能在您的web.xml中定义)。
如果您只是调用了doFilter,那么是的,您将拥有无限递归和堆栈溢出。但是,您正在调用filterChain对象的doFilter方法,该方法指示它执行下一个过滤器。

1

使链中的下一个过滤器被调用,或者如果调用的过滤器是链中的最后一个过滤器,则导致链末端的资源被调用。


0

是的,确切地说,这是一个递归调用。如果您将筛选器设置为文件夹,则会出现这种情况,

/javax.faces.resource/*

然后这个文件夹中的所有资源将被递归调用。所以如果你想对资源做一些操作,你需要编写以下代码:

    @Override
  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain)
      throws IOException, ServletException {
    doSomething(request, response);
    chain.doFilter(request, response);
  }

调用chain.doFilter(...)将处理当前请求/响应,然后调用下一个资源的doFilter,直到url-pattern中的所有资源都被后续的doFilter()调用处理。

假设您有一个ImagesFilter和SessionFilter实现。对于这些过滤器实现,您将使用URL-pattern定义filter-mapping。

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

路径 /* 中的所有资源都将由您的过滤器实现中的 doFilter(...) 方法调用,但最有趣的是 FilterChain 中的 doFilter 将执行请求/响应的实际处理。因此,如果您不调用 chain.doFilter(...),则可能会破坏您的响应。


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