Springboot 源码之 内嵌tomcat

server---service----engine----host-----context---wrapper---servlet

StandardServer---StandardService----StandartEngine----StandardHost----TomcatEmbeddedContext----StandardWrapper----DispatcherServlet

tomcat是一个io(nio)框架,是去网络连接里读取数据,然后一路流动到servlet中的

先看怎样读取数据:

EmbeddedWebApplicationContext在refresh()中的onRefresh()方法中,会调用createEmbeddedServletContainer()方法,先是生成tomcat,connector,Server,Service,Engine等

,然后生成TomcatEmbeddedServletContainer,在其构造方法中,有initialize()方法,会调用this.tomcat.start();方法中先检测server,connector这些,再调用server的start方法,这个

server是standardServer,(继承LifecycleBase的,实际逻辑都在startInternal方法中),start是调用下面所有的service的start,其实只有一个service,StandardService的start方法中,

1、Engine.start(先不说)

2、executor.start() 这个是线程池的启动

3、mapperListener.start() 这个很重要,以后的request是在这里获取DispatcherServlet

4、connector.start() 这个很重要,是nio启动的逻辑。里面显示protocalHandler的start,再就是NioEndPoint的start---startInternal(这些属性的装配先不说),

然后启动两个主要的组件:poller和acceptor,poller是NioEndPoint的内部类,实现了runnable接口,run方法内部的逻辑是经典的nio逻辑,

select注册在selector上面(怎么注册进来的下面说)所有的连接(Acceptor)的数据,交给线程池去处理。Poller的run方法里,

processKey(sk, attachment)->processSocket,把socketWrapper放到实现了runnable接口的SocketProcessorBase中,放到线程池里处理。SocketProcessorBase的run方法中核心

方法是getHandler().process(socketWrapper, event),调用processor.process(wrapper, status)方法,调用service(socketWrapper)方法,调用getAdapter().service(request, response)

方法,调用connector.getService().getContainer().getPipeline().getFirst().invoke(request, response),在pipeline中开始数据流动。service的container是engine,pipeline的first是null,

所以会调用默认的StandardEngineValve,取出request里面的host,调用host的pipeline链中 first.getNext()[next是StandardHostValve]的invoke,调用StandardContextValve的invoke,

从request中取出Wrapper,调用StandardWrapperValve的invoke方法,从host中取出filter,形成filterChain,把servlet(DispatcherServlet)放进去,然后是filterChain.dofilter,除了后面的

异常处理,这里是tomcat中,对request和response责任链的最后一步。再往下,就应该研究DispatcherServlet是怎样反射调用controller方法,配置参数,并处理返回结果的。

filterChain方法是调用internalDoFilter(),进来先判断当前进行到filter数组的哪一个位置,如果在数组内,执行filter的dofilter方法,如果在数组外,说明filter都执行完了,这时候并不直接返回,而是执行

servlet的service方法,这就是为什么我们自己写filter要调用filterChain.dofilter方法,因为这样的话,又递归进入internalDoFilter(),否则直接往下走,return了,之后的filter和servlet都不会调用。

而递归调用的结果是让pos这个位置变量往下移动,直到=n,就不会进入if(pos<n),而绕过return,跳到servlet里面。

知识兔
计算机