tomcat + spring mvc原理(五):tomcat Filter组件实现原理

tomcat + spring mvc原理(五):tomcat Filter组件实现原理

前言:

    原理(四)中假装结束了tomcat消息处理的流程分析,其实偷偷留了私货–Filter的这个部分依然属于tomcat网络消息处理的一个步骤。

Wrapper中Pipeline的收尾

    原理(四)最后用Wrapper中的StandardWrapperValve收尾,结论是

StandardWrapperValve是tomcat处理消息的边界,在这个Value的invoke()方法中,消息被传递给了Servlet,从此进入了spring mvc的领域。

StandardWrapperValve的invoke方法的实现代码很长,不过大部分内容都是异常的catch和处理,核心主要是获取Servlet实例、构建FilterChain、判断是否是异步Servlet和执行filterChain.doFilter方法。

   ······
   servlet = wrapper.allocate();
   
   ······
   ApplicationFilterChain filterChain =
        ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
        
   ······
   if (request.isAsyncDispatching()) {
    request.getAsyncContextInternal().doInternalDispatch();
   } else {
    filterChain.doFilter
        (request.getRequest(), response.getResponse());
   }
   ······

filterChain看上去很像原理(四)介绍的责任链,请求先依次经过注册Filter的处理,在最后会调用Servlet的service方法.到达Servlet就意味着请求被传递到了spring mvc中。Servlet的默认实现是DispatcherServlet,这部分内容会在spring mvc模块详细介绍。

Filter的基本实现

public interface Filter {
  
    public default void init(FilterConfig filterConfig) throws ServletException {}

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
                         throws IOException, ServletException;

    public default void destroy() {}
      
}

    在业务逻辑中添加Filter,就需要实现这个接口。FilterChain调用doFilter()方法时,依次调用注册的Filter的doFilter()方法,Filter是FilterChain中的基本单元。实际上,FilterChain中维护的是一个ApplicationFilterConfig的数组,这是因为在调用doFilter时,并不能保证Filter的实现类已经被加载到内存中,但是每一个注册过的Filter的类名(spring mvc在配置文件中配置,spring boot加载方式复杂一点)都会被保存在Context中。ApplicationFilterConfig中既有String变量保存类名,也有Filter的引用获取已经构造好的实例对象。

public final class ApplicationFilterConfig implements FilterConfig, Serializable {
    ·····
    private final transient Context context;

    private transient Filter filter = null;

    private final FilterDef filterDef;
    ·····
}

其中的FilterDef中就存储了filterClass的名字,这样在需要获取类实例时,就能直接newInstance()一个实例。

FilterChain的实现

    FilterChain中存储了ApplicationFilterConfig的数组,整数n用来存储数组的大小,整数pos用来存储当前调用的Filter的index。FilterChain的doFilter()实际调用internalDoFilter()来实现Filter链的遍历。首先是获取当前位置的Filter的实例,如果Filter的实现类的实例已经加载,filterConfig.getFilter()能够直接获取,如果没有加载,则根据类名构造一个实例。然后调用filter.doFilter(),其中传入了请求消息体、应答消息体和FilterChain自身。由于这个Filter的遍历并不是由循环而是由递归实现的,所以filter的doFilter()方法最后需要再次调用FilterChain的doFilter方法,这样FilterChain可以pos++,执行下一个filter的doFilter()。

public final class ApplicationFilterChain implements FilterChain {
    ......
    private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
    private int pos = 0;
    private int n = 0;
    private Servlet servlet = null;
    ......
    private void internalDoFilter(ServletRequest request,
                              ServletResponse response)
    throws IOException, ServletException {

    if (pos < n) {
        ApplicationFilterConfig filterConfig = filters[pos++];
        try {
            Filter filter = filterConfig.getFilter();
    ......
            } else {
                filter.doFilter(request, response, this);
            }
    ......
        } else {
            servlet.service(request, response);
        }
    ......
  }

在所有注册的Filter都遍历一遍之后,FilterChain会调用Servlet的service方法处理请求,自此,请求正式进入到spring mvc的领域。

最后解释一下ApplicationFilterFactory。ApplicationFilterFactory中的createFilterChain()方法中构造了一个ApplicationFilterChain对象,然后能够从Context中获得FilterMap,由这个FilterMap的内容填充了FilterChain的对象,这是就是FilterChain实现初始化的关键点。
相关文章:
tomcat + spring mvc原理(一):tomcat原理综述和静态架构
tomcat + spring mvc原理(二):tomcat容器初始化加载和启动
tomcat + spring mvc原理(三):tomcat网络请求的监控与处理1
tomcat + spring mvc原理(四):tomcat网络请求的监控与处理2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值