1.我们了解tomcat的意义
虽然现在Spring boot技术已经普及,但是,Spring boot,嵌入的tomcat其原理不会有多大的改变,我们如果想深入了解web项目,我觉得tomcat还是有必要稍微了解一下。因为,纵然springboot再怎么妖,万变不离其宗,而且,这么优秀的开源项目,其思想很值得借鉴,这边我稍微来说说,tomcat在加载Servlet的
过程。
2.为什么要用servlet和servlet 容器
首先 再Spring boot 出来之前,我估计绝大多数web 应用都部署在 web应用容器上面的吧因此,就出现了servlet 还有web容器,这些第都是为了处理http请求,解析分配url。servlet容器负责处理连接,分配请求。servlet负责对业务逻辑进行处理。这么设计也是为了最大的解耦,让业务开发人员屏蔽繁琐的连接和url的分配上解放出来,专注业务开发中去。
3.tomcat容器的分层
TomCat 有好几层容器 其中我们应用是部署在Container容器->Engine容器->Host容器-Context容器下
我们的每个servlet 会被包装在 对应Wrapper下。我们在Servlet的中,所说的容器其实就是Context容器。在tomcat中,我们可以认为一个war包对应一个Context容器(我猜想,当初tomcat的设计者没有想到,我们的互联网的体量会变得这么大,只是想的在一个节点下部署多个web应用,用tomcat来进行管理,不过自从我接触java以来,就没人这么玩过,估计是觉得,对维护单个项目太不方便了,一个项目要发布,其他项目都得停,这太不合理了。所以,我反而觉得这么设计有点重!至于为啥,我得在研究研究了)至于servlet对象会被包装成Wrapper对象,而不是Servlet对象,就是为了解耦吧,warpper是属于tomcat的,它起到代Servlet的作用,这是我个人看法。我们市面上其实有很多的servlet容器,但是无论哪种servlet容器,都可以加载,运行我们的servlet代码,我觉得都是通过类似tomcat的方案来进行解耦。越学习,越会发现那些优秀项目设计者的思想值得学习!
4.tomcat容器启动的过程
我们 tomCat 在启动的过程中,先分别启动Container容器->Engine容器->Host容器->Context容器。Context容器启动的过程中会加载web.xml文件,解析好的配置信息,会存放到WebXml 对象中(很像spring中的BeanDefinition),加载完成以后,再把WebXml 对象解析到Context容器中去。我们配置的servlet,filter等组件,都再WebXml对象中,Context容器会根据WebXml的对象信息,会将我们配置的Servlet,加载到StandradWarpper对象中,在这对象中,里面有对Servlet描述。不得不说这又和Spring bean 从applicationContext.xml文件中加载到Spring容器中的bean很像。这里再度表达一下这种设计思想实在是太伟大了。
5.Servlet加载过程
接下来,在加载完配置以后,如果这个时候,我们在web.xml 中如果配置了 load-on-startup为1以后,我们容器会加载servlet了,其实就是StandradWarpper通过反射工厂,来创建servlet实例化对象,然后执行我们写的init方法。这让我想起spring bean在实例化的过程中,通过反射实例化,调用bean的init方法,这样servlet就被加载起来了。
6.谈下我们日常项目启动过程
以上述过程中,我们可以来看下,我们传统非spring boot tomcat的启动过程。首先调用tomcat的startup方法。tomcat监听端口,启动各容器。启动容器过程中,加载web.xml配置。通常springMVC中会在web.xml文件中配置DispatcherServlet,默认都是容器启动。所以,在Context容器初始化完成以后,就会加载DispatcherServlet。而在初始化,执行servlet init方法的时候,就会初始化spring 容器,最终将spring 容器存放到ServletContext中,这样我们项目就通过tomcat可以被外部访问了。