提出问题,为什么要有Filter?
Filter的作用
1、filter可以拦截用户的非法请求,做权限验证。
2、filter可以做日志记录。
3、过滤一些敏感词。
Filter的生命周期
当服务器启动后,回先调用filter的构造器创建对象。创建完之后会立马调用 init() 方法,初始化filter。
当用户发送请求后,服务器会根据用户请求的url和filter的url-pattern相对比,如果匹配则调用filter的doFilter()方法。开发人员可以在doFilter中写一些拦截验证之类的判断,如果验证通过则调用 ApplicationFilterChain.doFIilter(request,response) 放行用户的请求,进入下一个filter,直到所有的filter都通过,则调用servlet或者jsp的service()方法,因为这里所有的filter的栈帧还没有结束,所以在service调用完后还会回溯 ApplicationFilterChain.daoFilter() 之后的业务逻辑判断,不会一般满足了一个条件通过后,后面的判断可以不用执行,因此一般可以在调用ApplicationFilterChain.doFilter()之后,调用return,避免影响其他的业务逻辑。
ApplicationFilterChain
ApplicationFilterChain是FilterChain的实现类。
通过jad反编译得到ApplicationFilterChain的部分代码:
//这一块数组默认长度等于0,如果有用户注册了filter,ApplicationFilterChain会调用addFilter()方法给数组扩容。
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
//当前filter的位置
private int pos = 0;
//filter的个数
private int n = 0;
//用户要访问的servlet
private Servlet servlet = null;
自定义的filter在执行完chain.doFilter()方法之后,通过过滤链中所有的过滤器之后,才去执行serlvet的service()方法,执行完service()方法之后,由于这时候filter的栈帧还没有结束,所以还要回溯完所有的栈帧。
注意
过滤器调用了chain.doFilter()方法后,最好后面紧跟return;这样即使这个filter的栈帧没有执行完,到回溯的时候也不会对其他的业务逻辑有影响。
多个filter的调用有点类似于递归,但是它和递归不同;递归是调用自己,而这里是多个不同的filter在调用。
自定的Filter是如何存进ApplicationFilterChain中链数组的?或者说是谁负责执行这个过程。