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)的更多相关文章

  1. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  2. 查看和指定SpringBoot内嵌Tomcat的版本

    查看当前使用的Tomcat版本号 Maven Repository中查看 比如我们需要查Spring Boot 2.1.4-RELEASE的内嵌Tomcat版本, 可以打开链接: https://mv ...

  3. SpringBoot内嵌Tomcat开启APR模式(运行环境为Centos7)

    网上查到的一些springboot内嵌的tomcat开启apr的文章,好像使用的springboot版本较老,在SpringBoot 2.0.4.RELEASE中已经行不通了.自己整理了一下,供参考. ...

  4. springboot去除内嵌tomcat和打包在tomcat中运行需要做的步骤

    去除内嵌tomcat和添加jsp依赖 去除内嵌tomcat 在springboot启动依赖中去除内嵌tomcat <dependency> <groupId>org.sprin ...

  5. SpringBoot内置的各种Starter是怎样构建的?--SpringBoot源码(六)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 温故而知新 本篇接 外部配置属性值是如何被绑定到XxxProperties类属性上的?--SpringBoot源码(五) 温 ...

  6. SpringBoot内置生命周期事件详解 SpringBoot源码(十)

    SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringBoot事件监听 ...

  7. SpringBoot源码学习系列之嵌入式Servlet容器

    目录 1.博客前言简单介绍 2.定制servlet容器 3.变换servlet容器 4.servlet容器启动原理 SpringBoot源码学习系列之嵌入式Servlet容器启动原理 @ 1.博客前言 ...

  8. SpringBoot的启动流程是怎样的?SpringBoot源码(七)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 温故而知新 本篇接 SpringBoot内置的各种Starter是怎样构建的? SpringBoot源码(六) 温故而知新, ...

  9. springboot源码(4)

    我们上3个篇章写了springboot的自动装配.servlet组件的注入以及web容器实现内嵌的原理,现在我们来看springboot启动过程中到底做了些什么,也就是打开我们的run方法: 这里我们 ...

  10. 内嵌tomcat启动速度慢

    项目上最近要把内置的jetty换成tomcat, 来更好的支持servlet 3.0 本来以为换个容器, 几十行代码就好了. 实际上换了tomcat后, 一开始启动tomcat, 非常的慢. jett ...

随机推荐

  1. 提供HTML5播放RTSP流 提供微信播放RTSP流 HTML5支持rtsp web播放rtsp,微信支持rtsp

    首先H5的video不支持RTSP播放,以下是html5的video官方介绍 现在如果要在页面中使用video标签,需要考虑三种情况,支持Ogg Theora或者VP8(如果这玩意儿没出事的话)的(O ...

  2. 网站性能测试工具 webbench 的安装和使用

    1.webbench的下载和安装 wget http://home.tiscali.cz/~cz210552/distfiles/webbench-1.5.tar.gz sudo tar xvf we ...

  3. WSGI协议主要包括server和application两部分:

    WSGI server负责从客户端接收请求,将request转发给application,将application返回的response返回给客户端:WSGI application接收由server ...

  4. My Team——面向对象与软件工程实验三

    My Team 一.Name GDTX(团队成员姓氏的拼音首字母组成) 二.项目描述 微信小程序(小洁便签): 1,功能齐全:小洁便签具有大多数便签APP所具有的添加.查看.修改和删除便签内容以及插入 ...

  5. python学习之读写csv文件(使用pandas)

    简介 逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本).纯文本意味着该文件是一个字符序 ...

  6. Petrozavodsk Winter Camp, Warsaw U, 2014, A The Carpet

    一个地图上有若干障碍,问允许出现一个障碍的最大子矩形为多大? 最大子矩形改编 #include<bits/stdc++.h> using namespace std; #define re ...

  7. python 报错 TabError: inconsistent use of tabs and spaces in indentation

    写python的时候如果出现如题的错误 TabError: inconsistent use of tabs and spaces in indentation 意为:制表符错误:缩进中制表符和空格使 ...

  8. springboot使用fastjson中文乱码解决方法 【转载】

    以前使用fastjson替换jackson时,没有直接在页面打印过json,都是js使用没有出现乱码,偶然 打印出来出现了中文乱码 之前使用的配置方式 @Configuration public cl ...

  9. linux bash array list

    #定义array ptpArray=()while read linedo #将文件读取内容放到array中,注意作为字符串放,否则空格会被分隔成行ptpArray+=("$line&quo ...

  10. Emacs中的代码折叠控制

    之前在别的编辑器里用到代码折叠的功能很好用. 对 Emacs 不够熟悉,作为一只坚强的懒癌晚期患者,一直没开启这个功能,使用石器时代的标记法来记录每个结构的起止位置,效率可想而知. 今天可算是找着它啦 ...