概述
由一组处理器依次处理某个数据,在处理过程中可能对数据进行修改。
详细
因为程序员相对的对Filter最熟悉,这里类图以filter为例。实际Spring下的Filter会比这个复杂的多,中间隔了很多GenericFilterBean、OncePerRequestFilter等类,这里是简化图
图中包含三类角色:
被处理的对象:request和response,被处理的对象可以是一个可以是多个,Filter中是这一对
过滤器链:负责如下事情
- 存储所有需要执行的过滤器
- 过滤器链的开始过滤
- 通过遍历判断过滤器链是否执行完成
过滤器每次执行完后会返回到过滤器链,过滤器链判断有没有完成。过滤器可以选择不返回过滤器直接return的!
过滤器:负责处理请求和决定是否把请求还给流水线,流水线往下一个节点走。
举一个没有还给流水线的例子:
DefaultLogoutPageGeneratingFilter类
//省略了部分代码
public class DefaultLogoutPageGeneratingFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (this.matcher.matches(request)) {
// 走到这个分支的时候是不还的,直接返回了
renderLogout(request, response);
}
else {
if (logger.isTraceEnabled()) {
logger.trace(LogMessage.format("Did not render default logout page since request did not match [%s]",
this.matcher));
}
filterChain.doFilter(request, response);
}
}
}
时序图:
本时序图假设总共就3个过滤器,其中第二个过滤器的实现类有直接return的条件分支。
所以途中有两个分支,一个分支是继续遍历调用后面的过滤器
一个是直接return
FilterChain的doFilter的伪代码:
private Filter[] filters = 所有的过滤器。
public void doFilter(ServletRequest request,ServletResponse response){
int n = 过滤器总数;
int pos = 当前过滤器位置;
if(pos<n){
filters[post++].doFilter(request, response);
}
}
所以如果FilterChain的doFilter方法不被调用的话,他是不会继续执行下一个过滤器的,因此过滤器本身具备了停止执行后面过滤器的权限,他只要return就行。