【Tomcat】【四】Pipeline-Value 管道
1 前言
上节讲了Container 自身的创建过程,Container处理请求是使用 Pipeline-Value管道来处理的,本节就详细分析一下 Pipeline-Value 管道。首先介绍它的处理模式,然后分析其实现方法。
2 Pipeline-Value处理模式
Pipeline-Value是责任链模式,责任链模式是指在一个请求处理的过程中有多个处理者依次对请求进行处理,每个处理者负责做自已相应的处理,处理完成后将处理后的请求返回,再让下一个处理者继续处理,就好像驾车的过程中可能会遇到很多次交警检查,可能有查酒驾的也可能有查违章的,在一次驾车的过程中可能会遇到多次检查,这就是责任链模式Pipeline就相当于驾车的过程,Value相当于检查的交警。
不过 Pipeline-Value 的管道模型和普通的责任链模式稍微有点不同,区别主要有两点D每个Pipeline都有特定的 Value,而且是在管道的最后一个执行,这个 Value 叫 BaseValueBaseValue 是不可删除的:2在上层容器的管道的 BaseValue 中会调用下层容器的管道。这就好像快递的配货车,配货车除了在路途中可能遇到交警检查外,到达目的地后必然还会被中转站检查货物,这是必不可少的,如果在中转站检查后没有问题就会把货物交给另外的货车去派送,直到将货物送到客户手中,被客户检查并签收。4个容器的 BaseValue 分别是StandardEngineValveStandardHostValve、StandardContextValve 和 StandardWrapperValve,整个处理的流程如图 7-5所示。
在Engine的管道中依次执行 Engine 的各个 Value,最后执行StandardEngineValve,用于调用Host的管道,然后执行 Host 的 Value,这样依次类推最后执行 Wrapper管道中的StandardWrapperValve。
在Filter 中用到的 FilterChain 其实就是这种模式,FilterChain相当于 Pipeline,每个 Filter都相当于一个Value,Servlet 相当于最后的BaseValue。
3 Pipeline-Value的实现方法
Pipeline管道的实现分为生命周期管理和处理请求两部分,下面分别介绍:
3.1 Pipeline管道生命周期的实现方法
Container 中的 Pipeline 在抽象实现类 ContainerBase 中定义,并在生命周期的startInternal.stopInternal、destroyIntermal方法中调用管道的相应生命周期方法(因为管道不需要初始化所以initInternal方法中并没有调用),代码如下:
Container的4个子容器都继承自ContainerBase,所以4个子容器在执行生命周期的方法时都会调用管道相应的生命周期方法。
Pipeline使用的是StandardPipeline 类型,它里面的 Value 保存在 first 属性中,Value 是式结构,可以通过 getNext方法依次获取每个 Value,BaseValue 单独保存在 basic 属性中(basic不可以为空,在调用addValve 方法添加 Value 时 basic 会同时保存到frst 的最后一个,如果没调用addValve方法则first可能为空)。StandardPipeline 继承自 LifecycleBase,所以实际处理生命周期的方法是startInternal、stopInternal和destroyInternal,代码如下:
startInternal方法和stopInternal方法处理的过程非常相似,都是使用临时变量current来遍历 Value链里的所有 Value,如果frst为空则使用 basic,然后遍历所有 Value 并调用相应的start和stop 方法,然后设置相应的生命周期状态。destroyInternal方法是删除所有 Value.
getValues方法可以得到包括 basic在内的所有 Value 的集合,代码如下:
3.2 Pipeline管道处理请求的实现方法
Pipeline调用所包含 Value的invoke 方法来处理请求,并且在 BaseValue 里又调用了子容器 Pipeline 所包含 Value 的 invoke 方法,直到最后调用了 Wrapper 的 Pipeline 所包含的 BaseValueStandardWrapperValve。
Connector在接收到请求后会调用最顶层容器的 Pipeline 来处理,顶层容器的 Pipeline处理完之后就会在其 BaseValue 里调用下一层容器的Pipeline 进行处理,这样就可以逐层调用所有容器的 Pipeline 来处理了。Engine 的 BaseValue 是StandardEngineValve,它的invoke 代码如下:
这里的实现非常简单,首先从 request 中获取到 Host,然后调用其管道的第一个 Value的invoke方法进行处理。Host 的 BaseValue 也同样会调用Context 的 Pipeline,Context的BaseValue 会调用 Wrapper 的 Pipeline,Wrapper 的 Pipeline 最后会在其 BaseValue ( StandardWrapperValve)中创建 FilterChain 并调用其 doFilter 方法来处理请求FilterChain 包含着我们配置的与请求相匹配的 Filter 和 Servlet,其 doFilter 方法会依次调用所有 Filter 的 doFilter 方法和Servlet的 service 方法,这样请求就得到处理了。
Filter 和Servlet 实际处理请求的方法在 Wrapper 的管道 Pipeline 的 BaseValueStandardWrapperValve 中调用,生命周期相关的方法是在 Wrapper 的实现类StandardWrapper 中调用。
4 小结
本节我们主要看了下 Pipeline-Value的实现过程,有理解不对的地方欢迎指正哈。