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(),再判断是不是在数组内。如果不递归调用filterChain.dofilter,那么会往下走,
直接return了,之后的filter和servlet都不会调用。而递归调用的结果是让pos这个位置变量往下移动,直到=n,就不会进入if(pos<n),而绕过return,跳到servlet里面。
request的host属性中,children一直向下走,到wrapper的时候,会有两个wrapper,一个defaultWrapper,一个dispatcherServletWrapper。但是拦截器链中,往下一步走并不是一定是去children中取子容器,
从StandardContextValve中取出wrapper,就是从request的mappingData这个属性中取出wrapper,所以会直接取到dispatcherServletWrapper。而dispatcherServletWrapper的赋值,是在CoyoteAdapter
第337行,postParseSuccess = postParseRequest(req, request, res, response)------679行,connector.getService().getMapper().map(serverName, decodedURI, version, request.getMappingData());
把service中的mapper中的属性,一个个的赋值给request的mappingData属性,第1111行,mappingData.wrapper = contextVersion.defaultWrapper.object,这里“=”后面就是dispatcher的wrapper,
至于contextVersion.defaultWrapper.object这属性为什么直接就是dispatcherServletWrapper,是筛选的时候,检测wrapper中的servlet所匹配的路径,(动态匹配?根据url匹配?)
Q2:所有的filter都是FilterRegistrationBean注册的?是怎么注册的?
springboot源码之(内嵌tomcat)的更多相关文章
- 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- 查看和指定SpringBoot内嵌Tomcat的版本
查看当前使用的Tomcat版本号 Maven Repository中查看 比如我们需要查Spring Boot 2.1.4-RELEASE的内嵌Tomcat版本, 可以打开链接: https://mv ...
- SpringBoot内嵌Tomcat开启APR模式(运行环境为Centos7)
网上查到的一些springboot内嵌的tomcat开启apr的文章,好像使用的springboot版本较老,在SpringBoot 2.0.4.RELEASE中已经行不通了.自己整理了一下,供参考. ...
- springboot去除内嵌tomcat和打包在tomcat中运行需要做的步骤
去除内嵌tomcat和添加jsp依赖 去除内嵌tomcat 在springboot启动依赖中去除内嵌tomcat <dependency> <groupId>org.sprin ...
- SpringBoot内置的各种Starter是怎样构建的?--SpringBoot源码(六)
注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 温故而知新 本篇接 外部配置属性值是如何被绑定到XxxProperties类属性上的?--SpringBoot源码(五) 温 ...
- SpringBoot内置生命周期事件详解 SpringBoot源码(十)
SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringBoot事件监听 ...
- SpringBoot源码学习系列之嵌入式Servlet容器
目录 1.博客前言简单介绍 2.定制servlet容器 3.变换servlet容器 4.servlet容器启动原理 SpringBoot源码学习系列之嵌入式Servlet容器启动原理 @ 1.博客前言 ...
- SpringBoot的启动流程是怎样的?SpringBoot源码(七)
注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 温故而知新 本篇接 SpringBoot内置的各种Starter是怎样构建的? SpringBoot源码(六) 温故而知新, ...
- springboot源码(4)
我们上3个篇章写了springboot的自动装配.servlet组件的注入以及web容器实现内嵌的原理,现在我们来看springboot启动过程中到底做了些什么,也就是打开我们的run方法: 这里我们 ...
- 内嵌tomcat启动速度慢
项目上最近要把内置的jetty换成tomcat, 来更好的支持servlet 3.0 本来以为换个容器, 几十行代码就好了. 实际上换了tomcat后, 一开始启动tomcat, 非常的慢. jett ...
随机推荐
- Activiti 工作流之所学所感(基本配置) DAY1
由于公司需求,最近在研究工作流,在此记录一下所学所感以备往后使用时候可以方便查询,有不足之处请各位大牛提点,下面直接进入主题. 下载activiti 所需资料 可以直接在官网上下载,也可以在我的网盘 ...
- CSS之实现垂直时间线展示相关内容效果
如下,最近在工作中遇到实现时间线效果的需求,用纯css即可实现,下面给出详细实现代码. html: <div class="time_line_list_wrap hide" ...
- nginx的前世今生
Nginx最初的设计是称为一个http服务器,一个能够解决C10K问题的http服务器. 那么问题来了,什么是C10K呢?C10K问题即(单机10万个并发链接问题),这个概念最早是由Dan Kegel ...
- Envoy 源码分析--event
目录 Envoy 源码分析--event libevent Timer SignalEvent FileEvent RealTimeSystem 任务队列 延迟析构 dispacth_thread E ...
- Azure中block和Page的比较 Azure: Did You Know? Block vs Page Blobs
Azure storage service supports two types of blobs (blob, or BLOB, stand for Binary Large OBject, i.e ...
- 采用Tensorflow内部函数直接对模型进行冻结
# enhance_raw.py # transform from single frame into multi-frame enhanced single raw from __future__ ...
- WPF程序打包发布
1.新建安装项目: 新建项目——其他项目类型——安装与部署——InstallShield Limited Edition Project 2.配置安装信息: 选择Project Assistant进入 ...
- TCP协议,UDP,以及TCP通信服务器的文件传输
TCP通信过程 下图是一次TCP通讯的时序图.TCP连接建立断开.包含大家熟知的三次握手和四次握手. 在这个例子中,首先客户端主动发起连接.发送请求,然后服务器端响应请求,然后客户端主动关闭连接.两条 ...
- 8、TypeScript-解构赋值
1.数组的解构赋值 2.对象的解构赋值 注意:在浏览器环境中,windows本身有一个成员name,所以要重新,语法为 属性名:重命名 3.函数的解构赋值
- Oracle单机Rman笔记[5]---脱机异地还原
脱机异地还原(安装一个原环境相同的linux,并安装数据库,注意不要配置安装实例) .检查/home/oracle下的.bashrc .bash_profile内容是否与原环境一致(具体看情况而定), ...