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 ...
随机推荐
- Jmeter 获取系统时间,和对系统时间进行增减时间
今天做了一个测试,比如发送短信验证码之后的, 验证90s被验证码有效的问题 那如何测试开发的代码,判断了90s内有效呢1. 验证码获取时间距离现在89秒,验证通过2. 验证码获取时间距离现在90秒,验 ...
- CentOS7.X怎样更新yum源
1. 备份原来的yum源 $sudo cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo-backup 2.设 ...
- 牛客 黑龙江大学程序设计竞赛重现 19-4-25 D
题意: n项工作 1~n 工时s[i] ~e[i], 工时有覆盖的工作不能被同一台机器同时操作, 问完成所有工作的最少机器数 思路:前缀差分和 e.g. a 2 3 4 ...
- 第 9 章 数据管理 - 075 - 配置 VirtualBox backend
配置 VirtualBox backend 在 VirtualBox 宿主机上启动 vboxwebsrv 服务: C:\Program Files\Oracle\VirtualBox > VBo ...
- (6)tcp-socket
(1)client端口: import socket# 产生一个socket对象sk = socket.socket()# 建立连接sk.connect( ("127.0.0.1" ...
- gm图片处理器:The gm/convert binaries can't be found
今天在使用node处理模块gm的时候,总是无法正常使用,报:The gm/convert binaries can't be found(找不到gm/convert二进制文件) google了一下,发 ...
- vue单位文本控件与vue加密文本控件
vue单位文本控件: 使用方式: npm install dami-text-input --save 使用: <text-input v-model="test" :uni ...
- ranch 源码分析(完)
接上 ranch 源码分析(三) 在上一次,根据ranch源码把大概流程理了一遍,下面我们将一些细节解释一下. ranch只是一个服务的框架,它提供了传输层协议代码(ranch_tcp 和ranch_ ...
- android --- api json数据
「一个」.「Time 时光」.「开眼」.「一席」.「梨视频」.「微软必应词典」.「金山词典」.「豆瓣电影」.「中央天气」.「魅族天气」.「每日一文」.「12306」.「途牛」.「快递100」.「快递」 ...
- python webdriver api-对启动的火狐浏览器添加配置
Webdriver启用的火狐不带插件,可以自已进行配置 先找到火狐的安装路径 C:\Program Files\Mozilla Firefox 步骤说明 在CMD中使用cd命令进入firefox.ex ...