前言
我们知道,假如我们在web应用中 设置了三个过滤器 1,2,3,那么执行流程应该是
过滤器1》过滤器2》过滤器3》具体业务》过滤器3》过滤器2》过滤器1
我当初想web容器是如何做到这个执行顺序的呢,最开始考虑的就是 是否采用的动态代理,因为相当于对 业务方法进行了 加强,但是仔细一想,如果是通过 动态代理,那么 业务方法 执行前应该是一个代码段 执行后应该是一个代码段,那 filter 的设计应该是 有一个 start()方法,一个 end()方法,但很明显 filter 的方法不是这样的。偶然点进去了一个 FilterChain 的实现类
public class MockFilterChain implements FilterChain {
private ServletRequest request;
private ServletResponse response;
private final List<Filter> filters;
private Iterator<Filter> iterator;
//......中间忽略
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
Assert.notNull(request, "Request must not be null");
Assert.notNull(response, "Response must not be null");
if (this.request != null) {
throw new IllegalStateException("This FilterChain has already been called!");
} else {
if (this.iterator == null) {
this.iterator = this.filters.iterator();
}
if (this.iterator.hasNext()) {
Filter nextFilter = (Filter)this.iterator.next();
nextFilter.doFilter(request, response, this);
}
this.request = request;
this.response = response;
}
}
}
然后自己简单模拟了一下
尝试
//过滤器接口
package TestFilterChain.iface;
import TestFilterChain.MyFilterChain;
import java.util.Map;
/**
* @date 2018/7/31 12:36
* @description
*/
public interface MyFilter {
void doFilter(Map<String,Object> param, MyFilterChain filterChain);
}
//servlet接口
package TestFilterChain.iface;
/**
* @date 2018/7/31 12:51
* @description
*/
public interface MyServlet {
void doPost();
void doGet();
}
//过滤器实现类
package TestFilterChain.impl;
import TestFilterChain.MyFilterChain;
import TestFilterChain.iface.MyFilter;
import java.util.Map;
/**
* @date 2018/7/31 12:54
* @description
*/
public class MyFilterImpl implements MyFilter{
@Override
public void doFilter(Map<String, Object> param, MyFilterChain filterChain) {
System.out.println("请求参数:"+param.toString());
filterChain.doFilter();
System.out.println("请求结束");
}
}
// servlet实现类
package TestFilterChain.impl;
import TestFilterChain.iface.MyServlet;
/**
* @date 2018/7/31 12:53
* @description
*/
public class MyServletImpl implements MyServlet {
@Override
public void doPost() {
System.out.println("处理逻辑");
}
@Override
public void doGet() {
doPost();
}
}
//拦截器链模拟类
package TestFilterChain;
import TestFilterChain.iface.MyFilter;
import TestFilterChain.iface.MyServlet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @date 2018/7/31 12:35
* @description
*/
public class MyFilterChain {
/**
* 需要执行的任务
*/
private MyServlet myServlet;
/**
* 封装请求参数
*/
private Map<String,Object> args;
/**
* 过滤器集合
*/
private List<MyFilter> myFilterList;
/**
* 迭代器
*/
private Iterator<MyFilter> iterator;
public MyFilterChain(List<MyFilter> myFilterList,Map<String,Object> args,MyServlet myServlet) {
this.myFilterList = myFilterList;
this.args = args;
this.myServlet = myServlet;
iterator = myFilterList.iterator();
myFilterList.subList(0,1);
}
public List<MyFilter> getMyFilterList() {
return myFilterList;
}
public void setMyFilterList(List<MyFilter> myFilterList) {
this.myFilterList = myFilterList;
}
/**
* 执行filter链的入口
*/
public void doFilter(){
if (iterator.hasNext()){
iterator.next().doFilter(args,this);
}else {
//执行servlet的逻辑
myServlet.doGet();
}
}
}
//web 容器模拟类
package TestFilterChain;
import TestFilterChain.iface.MyFilter;
import TestFilterChain.iface.MyServlet;
import TestFilterChain.impl.MyFilterImpl;
import TestFilterChain.impl.MyServletImpl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @date 2018/7/31 12:57
* @description
*/
public class WebContainer {
//处理一个请求
public static void main(String[] args) {
//模拟请求参数
Map<String,Object> param = new HashMap<>();
param.put("userName","111111");
param.put("password","222222");
//模拟处理的servlet
MyServlet servlet = new MyServletImpl();
//模拟定义的 List<filter>
List<MyFilter> filters = new ArrayList<>();
MyFilter filter = new MyFilter() {
@Override
public void doFilter(Map<String, Object> param, MyFilterChain filterChain) {
System.out.println("filter_1 start");
filterChain.doFilter();
System.out.println("filter_1 end");
}
};
MyFilter filter2 = new MyFilter() {
@Override
public void doFilter(Map<String, Object> param, MyFilterChain filterChain) {
System.out.println("filter_2 start");
filterChain.doFilter();
System.out.println("filter_2 end");
}
};
filters.add(filter);
filters.add(filter2);
//执行
MyFilterChain filterChain = new MyFilterChain(filters,param,servlet);
filterChain.doFilter();
}
}
//输出结果
filter_1 start
filter_2 start
处理逻辑
filter_2 end
filter_1 end
总结
我理解的流程是:
当客户端发送一个请求时,web容器对这个请求处理过程:
1.根据url 路径,匹配对应的 filter/servlet
2.封装 HttpServletRequest 与 HttpServletResponse 对象
3.把 filter/servlet/req/res 封装到一个拦截器链对象中
4.调用拦截器链对象的 doFilter() 方法
5.doFilter() 方法中,先尝试从过滤器结合的迭代器中获取过滤器。如果获取到,就执行过滤器的 doFilter() 方法,并把过滤器链一起传给过滤器,过滤器控制是否再执行 过滤器链 的 doFilter() 方法。如果没获取到,说明过滤器执行完毕或无过滤器需要执行,则执行 业务逻辑方法。感觉很像一个递归
后记
以上纯属个人的一些理解,有不对的地方还请大家指出来。