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 ...
随机推荐
- spark DAG 笔记
DAG,有向无环图,Directed Acyclic Graph的缩写,常用于建模. Spark中使用DAG对RDD的关系进行建模,描述了RDD的依赖关系,这种关系也被称之为lineage,RDD的依 ...
- golang Mysql -- Tx
Transaction 事务 事务处理是数据的重要特性.尤其是对于一些支付系统,事务保证性对业务逻辑会有重要影响.golang的mysql驱动也封装好了事务相关的操作.我们已经学习了db的Query和 ...
- 本地连接属性:Internet协议版本4(TCP/IPv4)打开闪退解决办法
1.命令窗口配置网络连接指定IP netsh interface ip set address "本地连接" static IP地址 子网掩码 默认网关 例:netsh inter ...
- CF Manthan, Codefest 16 B. A Trivial Problem
数学技巧真有趣,看出规律就很简单了 wa 题意:给出数k 输出所有阶乘尾数有k个0的数 这题来来回回看了两三遍, 想的方法总觉得会T 后来想想 阶乘 emmm 1*2*3*4*5*6*7*8*9 ...
- Spring框架IOC和AOP的实现原理(概念)
IoC(Inversion of Control) (1). IoC(Inversion of Control)是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控.控制权由应用代码中 ...
- 百度ueditor上传图片时如何设置默认宽高度
百度ueditor上传图片时如何设置默认宽高度 一.总结 一句话总结:直接css或者js里面限制一下就好,可以用html全局限制一下图片的最大高度 直接css或者js里面限制一下就好,可以用html全 ...
- python爬虫采集网站数据
1.准备工作: 1.1安装requests: cmd >> pip install requests 1.2 安装lxml: cmd >> pip install lxml ...
- (6)tcp-socket
(1)client端口: import socket# 产生一个socket对象sk = socket.socket()# 建立连接sk.connect( ("127.0.0.1" ...
- 小账本APP——软件项目风险管理及解决办法案例
小账本APP——软件项目风险管理及解决办法案例 摘要 软件项目风险是指在软件开发过程中遇到的预算和进度等方面的问题以及这些问题对软件项目的影响.软件项目风险会影响项目计划的实现,如果项目风险变成现实, ...
- ERP新人防坑指南
本文作为初入ERP行业的新人的防坑指南,讲解了一些常见犯的错,这样也少走一些弯路,如果你是老鸟,请绕过 :-) 本文关联的代码使用kotlin编写,请自行转换为c#.java等你熟悉的语言,表述的坑在 ...