通过上一节我们完成了对容器进行了加载、初始化、启动,而对于应用的加载部分独立出来,本节进行单独的讲解
 

一、应用加载流程

1)应用识别,Context创建

  • 在Host启动后,会调用Host的监听HostConfig进行启动事件处理
  • HostConfig在监听到启动事件后,会分别尝试从context.xml下,wabapps下war,webapp下文件夹进行应用的读取,读取过程中通过Host的启停线程池(startStopExecutor)进行独立线程读取,读取最终结果生成Context对象并添加进入Host容器中。注意这里用到了Future<?>协同方式
  • 这里构建的Context仅包含如下基本参数(如:name,path,webappVersion,docBase),另外会给Context默认增加监听ContextConfig
 

2)应用加载,Context启动

    • Engine启动ContainerBackgroundProcessor线程进行对所有容器进行后台处理,即调用所有容器的backgroundProcess()方法
    • 容器backgroundProcess()方法处理完成后,通知相应的监听器(事件类型为Lifecycle.PERIODIC_EVENT)
    • HostConfig会根据Context是否启动,进行相应启动操作(context.start()),
    • Context启动过程如下:
      • 获取一个WebAppLoader,
      • 应用类加载,执行WebAppLoader.start()方法,该方法内,会创建一个ClassLoader(WebappClassLoader),在调用ClassLoader.start()方法进行jar与class的加载
      • 添加应用级监听器至Context成员变量中,其中主要有:ServletContextAttributeListener,ServletRequestAttributeListener,ServletRequestListener,HttpSessionIdListener,HttpSessionAttributeListener,ServletContextListener,Context成员变量声明如下:
        private List<Object> applicationEventListenersList = new CopyOnWriteArrayList<>();
      • 执行SevletContextListener监听器上下文完成初始化方法(注意,Spring就是这里进行的初始化的)
    • Context启动完成后,通知相应的监听器ContextConfig,进行启动完成处理
    • ContextConfig.start()方法(核心为调用webConfig()方法)
      • 读取/WEB-INF/web.xml文件,构建WebXml对象
      • 解析所有class,判断是否有使用servlet相关注解(Ljavax/servlet/annotation/WebServlet),如果使用就注解对象手动添加至WebXml对象中,即生成ServletDef定义文件
      • 将jsp转换为ServletDef定义文件,并添加至WebXml对象中
      • 将WebXml对象内容解析至Context对象中(方法:configcontext),一个Servlet对应一个Wrapper容器

  1. for (Entry<String, String> entry : webxml.getContextParams().entrySet()) {
  2. context.addParameter(entry.getKey(), entry.getValue());
  3. }//context全局参数
  4. ....
  5. for (ErrorPage errorPage : webxml.getErrorPages().values()) {
  6. context.addErrorPage(errorPage);
  7. }//404页面
  8. for (FilterDef filter : webxml.getFilters().values()) {
  9. if (filter.getAsyncSupported() == null) {
  10. filter.setAsyncSupported("false");
  11. }
  12. context.addFilterDef(filter);
  13. }//拦截器
  14. for (FilterMap filterMap : webxml.getFilterMappings()) {
  15. context.addFilterMap(filterMap);
  16. }//拦截器Map
  17. context.setJspConfigDescriptor(webxml.getJspConfigDescriptor());
  18. for (String listener : webxml.getListeners()) {
  19. context.addApplicationListener(listener);
  20. }//监听器
  21. ......
  22. for (ServletDef servlet : webxml.getServlets().values()) {
  23. Wrapper wrapper = context.createWrapper();//一个servlet对应一个封装器Wrapper
  24. // Description is ignored
  25. // Display name is ignored
  26. // Icons are ignored
  27. // jsp-file gets passed to the JSP Servlet as an init-param
  28. if (servlet.getLoadOnStartup() != null) {
  29. wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
  30. }
  31. if (servlet.getEnabled() != null) {
  32. wrapper.setEnabled(servlet.getEnabled().booleanValue());
  33. }
  34. wrapper.setName(servlet.getServletName());
  35. Map<String,String> params = servlet.getParameterMap();
  36. for (Entry<String, String> entry : params.entrySet()) {
  37. wrapper.addInitParameter(entry.getKey(), entry.getValue());
  38. }
  39. wrapper.setRunAs(servlet.getRunAs());
  40. Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs();
  41. for (SecurityRoleRef roleRef : roleRefs) {
  42. wrapper.addSecurityReference(
  43. roleRef.getName(), roleRef.getLink());
  44. }
  45. wrapper.setServletClass(servlet.getServletClass());
  46. MultipartDef multipartdef = servlet.getMultipartDef();
  47. if (multipartdef != null) {
  48. if (multipartdef.getMaxFileSize() != null &&
  49. multipartdef.getMaxRequestSize()!= null &&
  50. multipartdef.getFileSizeThreshold() != null) {
  51. wrapper.setMultipartConfigElement(new MultipartConfigElement(
  52. multipartdef.getLocation(),
  53. Long.parseLong(multipartdef.getMaxFileSize()),
  54. Long.parseLong(multipartdef.getMaxRequestSize()),
  55. Integer.parseInt(
  56. multipartdef.getFileSizeThreshold())));
  57. } else {
  58. wrapper.setMultipartConfigElement(new MultipartConfigElement(
  59. multipartdef.getLocation()));
  60. }
  61. }
  62. if (servlet.getAsyncSupported() != null) {
  63. wrapper.setAsyncSupported(
  64. servlet.getAsyncSupported().booleanValue());
  65. }
  66. wrapper.setOverridable(servlet.isOverridable());
  67. context.addChild(wrapper);
  68. }
  69. for (Entry<String, String> entry :
  70. webxml.getServletMappings().entrySet()) {
  71. context.addServletMapping(entry.getKey(), entry.getValue());
  72. }
  73. //sesseionConfig对象
  74. SessionConfig sessionConfig = webxml.getSessionConfig();
  75. if (sessionConfig != null) {
  76. if (sessionConfig.getSessionTimeout() != null) {
  77. context.setSessionTimeout(
  78. sessionConfig.getSessionTimeout().intValue());
  79. }
  80. SessionCookieConfig scc =
  81. context.getServletContext().getSessionCookieConfig();
  82. scc.setName(sessionConfig.getCookieName());
  83. scc.setDomain(sessionConfig.getCookieDomain());
  84. scc.setPath(sessionConfig.getCookiePath());
  85. scc.setComment(sessionConfig.getCookieComment());
  86. if (sessionConfig.getCookieHttpOnly() != null) {
  87. scc.setHttpOnly(sessionConfig.getCookieHttpOnly().booleanValue());
  88. }
  89. if (sessionConfig.getCookieSecure() != null) {
  90. scc.setSecure(sessionConfig.getCookieSecure().booleanValue());
  91. }
  92. if (sessionConfig.getCookieMaxAge() != null) {
  93. scc.setMaxAge(sessionConfig.getCookieMaxAge().intValue());
  94. }
  95. if (sessionConfig.getSessionTrackingModes().size() > 0) {
  96. context.getServletContext().setSessionTrackingModes(
  97. sessionConfig.getSessionTrackingModes());
  98. }
  99. }
    • 从WebApp加载中读取ServletContainerInitializer的实现,并添加至context容器中
 
    至此,host下面的context,wrapper,等容器就就已经生成并初始化了。

【Tomcat源码学习】-3.应用管理的更多相关文章

  1. Tomcat源码学习(1)

    Tomcat源码学习(1) IntelliJ IDEA 17.3.3 导入 Tomcat 9.0.6源码 下载源码 tomcat_9.0.6 启动 IDEA. 点击 Open,选择刚才下载的文件解压后 ...

  2. Tomcat源码学习

    Tomcat源码学习(一) 转自:http://carllgc.blog.ccidnet.com/blog-htm-do-showone-uid-4092-type-blog-itemid-26309 ...

  3. 【Tomcat源码学习】-1.概述

    Tomcat是用java语言开发的一个Web服务器,最近花了差不多两周时间对Tomcat 9.0源码进行了一遍学习,由于知识储备有限,也只是理解了一个大概,下面就由我来给大家分享一下我对Tomcat的 ...

  4. Tomcat源码学习 - 环境搭建

    一. 源码下载 PS: 多图预警 在开始阅读源码之前,我们需要先构建一个环境,这样才能便于我们对源码进行调试,具体源码我们可以到官网进行下载(这里我以8.5.63版本为例). 二. 项目导入 下载并解 ...

  5. Tomcat源码学习记录--web服务器初步认识

    Tomcat作为开源的轻量级WEB服务器,虽然不是很适合某些大型项目,但是它开源,读其源代码可以很好的提高我们的编程功底和设计思维.Tomcat中用到了很多比较好的设计模式,其中代码风格也很值得我们去 ...

  6. TOMCAT源码分析——生命周期管理

    前言 从server.xml文件解析出来的各个对象都是容器,比如:Server.Service.Connector等.这些容器都具有新建.初始化完成.启动.停止.失败.销毁等状态.tomcat的实现提 ...

  7. Tomcat源码学习一

    这段时间工作不太忙,所以抽时间学习了TOMCAT, TOMCAT实际就是负责保持TCP连接传递到部署的项目中.浏览器实质就是TCP发送器.将用户的请求封装成TCP发送请求.当然格式是双方协定的.使用的 ...

  8. Mybatis源码学习之事务管理(八)

    简述 在实际开发中,数据库事务的控制是一件非常重要的工作,本文将学习Mybatis对事务的管理机制.在Mybatis中基于接口 Transaction 将事务分为两种,一种是JdbcTransacti ...

  9. Python 源码学习之内存管理 -- (转)

    Python 的内存管理架构(Objects/obmalloc.c): _____ ______ ______ ________ [ int ] [ dict ] [ list ] ... [ str ...

  10. 【Tomcat源码学习】-2.容器管理

    Tomcat作为应用服务器,我们可以理解Tomcat本身就是一个容器,用于装载应用,而作为容器本身是由若干组件以及事件构成,容器管理即为管理容器的有机组成部分.   一.Tomcat整体结构: Ser ...

随机推荐

  1. Java程序通过代理访问网络

    问题背景 最近工作上有开发爬虫的任务,对目标网站数据进行抓取,由于大部分网站都在国外,无法直接访问,需要通过代理才能登录.爬虫部署的服务器在香港,所以爬虫部署到服务器后,是可以访问目标网站的,但本地开 ...

  2. 写lua时需要注意的地方

    条件语句判断时,只有false和nil会导致判断为假,其他的任何值都为真. Lua 的字符串与编码无关: 它不关心字符串中具体内容. 标准 Lua 使用 64 位整数和双精度(64 位)浮点数, 但你 ...

  3. jQuery入门(一)

    相信学js的人多多少少听过JQuery,JQuery对于前端开发人员来说是不可或缺的,他让开发变得更加简单.那到底什么是JQuery呢?用一句话来说,JQuery就是一个javascript的库.所谓 ...

  4. [POJ1028]Web Navigation(栈)

    这题是01年East Central North的A题,目测是签到题 Description Standard web browsers contain features to move backwa ...

  5. Python 引用、浅拷贝、深拷贝解析

    引用 Python是动态数据类型的语言,故在对变量进行赋值时是不用制定变量类型的. 或者说,你可以把变量赋值的过程,当作是贴一个标签,去引用该数据. 看下面的例子: In [54]: a=4 In [ ...

  6. webots自学笔记(一)软件界面和简单模型仿真

    本人是某非理工类某高校大四狗,由于毕设研究需要使用webots软件,在学习使用webots的过程花费了很多时间.由于这个软件基本没有什么中文资料,所以想把自己所学到的一些东西写下来,如有什么错误的地方 ...

  7. 1084: [SCOI2005]最大子矩阵

    1084: [SCOI2005]最大子矩阵 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1325  Solved: 670[Submit][Stat ...

  8. maven项目无法查看方法

    问题如图: 解决:

  9. java中的递归

    所谓递归,是指程序调用自身,当然,递归不会无休止地调用下去,它必然有一个出口,当满足条件时程序也就结束了,不然的话,那就是死循环了. 看下面这个类,有几个递归方法,看了之后肯定会对你学习递归很有帮助的 ...

  10. HttpServletResponse对象介绍

    一.HttpServletResponse对象介绍