1 Tomcat 基本知识

首先介绍一些 Tomcat 的基本知识,防止有纯小白看的云里雾里的。

下面这张图是一个下载好二进制版的的 Tomcat ,直接解压得到的,虽然版本是 9.x ,但是这个目录结构和 8.5 是一致的,不影响介绍。

  • bin : 主要用来存放一些脚本文件,一种格式是 sh 的是在 Linux 使用的脚本,另一种格式是 bat 的是在 Windows 中使用的脚本。
  • conf : 主要用来存放一些 Tomcat 的配置文件,有 xml 格式的也有 properties 格式的。
  • lib : 用来存放一些 Tomcat 运行时所需要的 jar 包。
  • logs : 日志目录。
  • temp : 存放一些运行过程中产生的临时文件。
  • webapps : 这个应该很熟悉,主要用来存放应用程序,可以是 war 包或者是 jar 包。
  • work : 主要用来存放 Tomcat 在运行时的编译后文件。清空work目录,然后重启 Tomcat ,可以达到清除缓存的作用。

现在的 IDE(Integrated Development Environment) 工具可以直接将 Tomcat 配置在工具中,比如最常用的 Eclipse 和 IDEA ,启动 Tomcat 的时候只需要点一下按钮就可以启动,实际上这两个 IDE 工具只是帮我们调用了 Tomcat 的启动脚本。

Tomcat 的各种脚本都放在 bin 这个目录下,我们打开看一下:

可以轻易的找到两个启动脚本 startup.bat 和 startup.sh 。一个是 Windows 下的脚本,一个 Linux 下的。

同样,还可以看到两个停止脚本 shutdown.bat 和 shutdown.sh 。

这是在 Tomcat 的二进制包中,我们还可以看下源码包下是什么样的。

可以看到,基本上该有的都有,最重要的启停脚本都还在。

既然我现在是在 Windows 环境下,那么启动就从 startup.bat 看起。

2 Tomcat 启动第一步:startup.bat

第一个打开 startup.bat 这个启动脚本,看下里面写了啥具体,这段脚本不长,我把里面的内容摘出来:

setlocal

rem Guess CATALINA_HOME if not defined
set "CURRENT_DIR=%cd%"
if not "%CATALINA_HOME%" == "" goto gotHome
set "CATALINA_HOME=%CURRENT_DIR%"
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
cd ..
set "CATALINA_HOME=%cd%"
cd "%CURRENT_DIR%"
:gotHome
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat" rem Check that target executable exists
if exist "%EXECUTABLE%" goto okExec
echo Cannot find "%EXECUTABLE%"
echo This file is needed to run this program
goto end
:okExec rem Get remaining unshifted command line arguments and save them in the
set CMD_LINE_ARGS=
:setArgs
if ""%1""=="""" goto doneSetArgs
set CMD_LINE_ARGS=%CMD_LINE_ARGS% %1
shift
goto setArgs
:doneSetArgs call "%EXECUTABLE%" start %CMD_LINE_ARGS% :end

最开始一大段的 rem 注释我没摘,只摘了最后一部分会执行的内容。

第一段是在设置当前的 CATALINA_HOME 的环境变量,如果没有设置的话,会将当前运行脚本的目录作为该环境变量的值,然后跳转到 :okHome 那里。

接下来设置了 EXECUTABLE 的路径是 %CATALINA_HOME%\bin\catalina.bat 。

然后开始验证验证设置的 EXECUTABLE 中的 catalina.bat 这个文件存不存在,如果不存在的话直接结束,如果存在的话接着往下走。

接下来是将运行脚本前设置的其他参数保存到 CMD_LINE_ARGS 这个变量中,然后在最后执行了 catalina.bat 这个文件,跟了两个参数,第一个是 start ,第二个就是刚才保存的变量 CMD_LINE_ARGS 。

这种脚本代码建议放在编辑器里看,千万不要使用那个 Windows 自带的记事本,用那玩意看估计大多数人直接就看懵了。

我通常是放在 VSCode 中看,会自动对代码进行高亮展示,给大家看下上面这段脚本放在 VSCode 中的样子:

可以看到,正常注释变灰,关键字变蓝高亮,并且跳转语句直接变橙色,非常方便我们阅读。

3 Tomcat 启动第二步:catalina.bat

这个脚本太长了,我就单纯的截取比较重要的进行介绍。

set "CURRENT_DIR=%cd%"
if not "%CATALINA_HOME%" == "" goto gotHome
set "CATALINA_HOME=%CURRENT_DIR%"
if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
cd ..
set "CATALINA_HOME=%cd%"
cd "%CURRENT_DIR%"
:gotHome if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome
echo The CATALINA_HOME environment variable is not defined correctly
echo This environment variable is needed to run this program
goto end
:okHome

在最开头的地方,校验 CATALINA_HOME 是否存在,如果不存在,则设置 CATALINA_HOME 为当前路径。

接着下面设置了一下 CATALINA_BASE 这个变量。

if not "%CATALINA_BASE%" == "" goto gotBase
set "CATALINA_BASE=%CATALINA_HOME%"
:gotBase

接下来到了一个重点内容,判断 setclasspath.bat 是否存在,如果存在的话就执行一下:

rem Get standard Java environment variables
if exist "%CATALINA_HOME%\bin\setclasspath.bat" goto okSetclasspath
echo Cannot find "%CATALINA_HOME%\bin\setclasspath.bat"
echo This file is needed to run this program
goto end
:okSetclasspath
call "%CATALINA_HOME%\bin\setclasspath.bat" %1
if errorlevel 1 goto end

这个文件实际上是校验是否设置了 JAVA_HOME 或者 JRE_HOME 的环境变量,如果没有设置则会在控制台打印对应的信息。

接下来是有关于 CLASSPATH 的设置和校验,然后是一堆变量的设置和校验,无需关注,接着使用 echo 打印了一些信息:

echo Using CATALINA_BASE:   "%CATALINA_BASE%"
echo Using CATALINA_HOME: "%CATALINA_HOME%"
echo Using CATALINA_TMPDIR: "%CATALINA_TMPDIR%"
if ""%1"" == ""debug"" goto use_jdk
echo Using JRE_HOME: "%JRE_HOME%"
goto java_dir_displayed
:use_jdk
echo Using JAVA_HOME: "%JAVA_HOME%"
:java_dir_displayed
echo Using CLASSPATH: "%CLASSPATH%"

各种比较重要的变量在这里进行了一些打印,接下来又设置了一些比较重要的变量:

set _EXECJAVA=%_RUNJAVA%
set MAINCLASS=org.apache.catalina.startup.Bootstrap
set ACTION=start
set SECURITY_POLICY_FILE=
set DEBUG_OPTS=
set JPDA=

这里的 _EXECJAVA 实际上是我们在 JAVA_HOME 或者是 JRE_HOME 中 bin 下面的 java.exe 。

这里出现的 _RUNJAVA 变量,是在上面的 setclasspath.bat 那个脚本中进行设置的。

而这个 MAINCLASS 的值是 org.apache.catalina.startup.Bootstrap ,这个是我们第一篇文章启动 Tomcat 时候的那个类,不知道各位还有印象不。

接下来设置了一个变量 ACTION 的动作时 start ,用屁股想想应该是启动的意思。

然后对参数进行了一次判断:

if ""%1"" == ""debug"" goto doDebug
if ""%1"" == ""run"" goto doRun
if ""%1"" == ""start"" goto doStart
if ""%1"" == ""stop"" goto doStop
if ""%1"" == ""configtest"" goto doConfigTest
if ""%1"" == ""version"" goto doVersion

如果没有其他参数做覆盖,这里的参数就是上面设置的 start ,直接跳转到最后的 doStart 去了,不过可以看到, Tomcat 启动可以接受的参数有 debug , run , start , stop , configtest 和 version ,我们平时在 IDE 工具里用的比较多的应该有 debug , run , start , stop , 剩下的两个至少我是基本上没有使用过,如果不是今天看到这里了,我都不知道 Tomcat 还能有 configtest 和 version 这两个参数。

:doDebug
shift
set _EXECJAVA=%_RUNJDB%
set DEBUG_OPTS=-sourcepath "%CATALINA_HOME%\..\..\java"
if not ""%1"" == ""-security"" goto execCmd
shift
echo Using Security Manager
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd :doRun
shift
if not ""%1"" == ""-security"" goto execCmd
shift
echo Using Security Manager
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd :doStart
shift
if "%TITLE%" == "" set TITLE=Tomcat
set _EXECJAVA=start "%TITLE%" %_RUNJAVA%
if not ""%1"" == ""-security"" goto execCmd
shift
echo Using Security Manager
set "SECURITY_POLICY_FILE=%CATALINA_BASE%\conf\catalina.policy"
goto execCmd

上面这一段就是我们最常用的三种启动方式,从脚本上来看, debug 比 run 单纯的多设置了两个变量 _EXECJAVA 和 DEBUG_OPTS ,而 start 则是多了一个 TITLE 的判断。

接着往下看,基本上就已经到了这个脚本的最底部,这里执行了一句话,也是核心的一句话:

%_EXECJAVA% %CATALINA_LOGGING_CONFIG% %LOGGING_MANAGER% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -D%ENDORSED_PROP%="%JAVA_ENDORSED_DIRS%" -classpath "%CLASSPATH%" -Dcatalina.base="%CATALINA_BASE%" -Dcatalina.home="%CATALINA_HOME%" -Djava.io.tmpdir="%CATALINA_TMPDIR%" %MAINCLASS% %CMD_LINE_ARGS% %ACTION%

_EXECJAVA 是我们刚才说的那个 java.exe ,然后是各种运行时参数和系统属性,最后面的 MAINCLASS ,也就是 org.apache.catalina.startup.Bootstrap ,接着是 CMD_LINE_ARGS ,这也是一个命令参数,就是 main 方法上的那个 args 参数,最后一个参数是 ACTION 也就是 start 。

最后归根结底就是一句话,执行 Bootstrap 里面的 main 方法,别看这些个脚本写了一大堆,主要工作就是在校验环境配置以及一些基础系统设置和一些运行时参数的设置。

4 小结

脚本整体来讲不难,而且每段脚本上面都已经有了简单的英文注释,简明扼要的写清楚了这一段脚本在做什么,稍微了解一些基础的 DOS 命令,都可以进行阅读。

至于其他的脚本可以大致浏览下,基本上兜兜转转最后还是会回到 catalina.bat 这个脚本,而在这个脚本中,最后肯定会执行 Bootstrap 里面的 main 方法。

在 Windows 系统中,使用的是 bat 脚本,在 Linux 系统中,就会使用 sh 脚本,这个本质上没有什么大的差别,整体原理都是一样的,有兴趣的同学可以自己研究下 sh 脚本,就当学 shell 语法了。

Tomcat 第二篇:启动流程的更多相关文章

  1. 理解Tomcat架构、启动流程及其性能优化

    PS:but, it's bullshit ! 备注:实话说,从文档上扒拉的,文档地址:在每一个Tomcat安装目录下,会有一个webapps文件夹,里面有一个docs文件夹,点击index.html ...

  2. [知了堂学习笔记]_牵线Eclipse和Tomcat第二篇 —— 安装Tomcat&&添加Tomcat到Eclipse

    来了来了~~~~~我们的"织女"--Tomcat来了,牛郎们等急了吧!哈哈! 一.安装Tomcat 下载地址:http://tomcat.apache.org/download-7 ...

  3. Orchard详解--第二篇 启动

    Orchard Framework作为框架它与类库最大的区别就是框架是将一系列零散的组件组合在一起形成一个整体,接下来就对Orchard Framework如何分析Orchard如何将相关组件结合在一 ...

  4. js入门第二篇之流程控制语句

    表达式语句: 一个表达式可以产生一个值,有可能是运算.函数调用 字面量 表达式可以放在任何需要值的地方. 语句: 语句可以理解成一个行为,循环语句和判断语句就是典型的语句,一个程序有多个语句组成. 流 ...

  5. andriod and linux kernel启动流程

    虽然这里的Arm Linux kernel前面加上了Android,但实际上还是和普遍Arm linux kernel启动的过程一样的,这里只是结合一下Android的Makefile,讲一下boot ...

  6. 使用spring等框架的web程序在Tomcat下的启动顺序及思路理清

    大牛请绕过,此文仅针对自己小白水平,对web程序的启动流程做个清晰的回顾. 一.使用spring等框架的web程序在Tomcat下的启动流程 1)Tomcat是根据web.xml来启动的.首先到web ...

  7. Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析

    一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...

  8. 菜鸟nginx源代码剖析 框架篇(一) 从main函数看nginx启动流程

    菜鸟nginx源代码剖析 框架篇(一) 从main函数看nginx启动流程 Author:Echo Chen(陈斌) Email:chenb19870707@gmail.com Blog:Blog.c ...

  9. Tomcat启动流程简析

    Tomcat是一款我们平时开发过程中最常用到的Servlet容器.本系列博客会记录Tomcat的整体架构.主要组件.IO线程模型.请求在Tomcat内部的流转过程以及一些Tomcat调优的相关知识. ...

随机推荐

  1. sizeof的用法 2007-12-19 11:06

    sizeof的作用是什么?sizeof是C/C++中的一个操作符(operator),简单的说其作用就是返回一个对象或者类型所占的内存字节数.其返回值类型为size_t,在头文件stddef.h中定义 ...

  2. 浏览器自动化的一些体会6 增强的webBrowser控件

    这里谈两点 1.支持代理服务器切换 一种方法是修改注册表,不是太好的做法,而且,只能改全局设置,不能改局部(比如只让当前的webBrowser控件使用代理,而其他应用不用代理) 另外一个较好的方法,示 ...

  3. JAVA 读取excel文件成List<Entity>

    package com.fsinfo.common.utils; import com.fsinfo.modules.enterprise.entity.EnterpriseRecordEntity; ...

  4. Python版常见的排序算法

    学习笔记 排序算法 目录 学习笔记 排序算法 1.冒泡排序 2.选择排序 3.插入排序 4.希尔排序 5.快速排序 6.归并排序 7.堆排序 排序分为两类,比较类排序和非比较类排序,比较类排序通过比较 ...

  5. python爬虫用drony转发进行抓包转发

    转载至https://www.cnblogs.com/lulianqi/p/11380794.html#l_2 实际操作步骤(Android) 笔者这里直接使用上面提到第3种方法(方法1在对于手机AP ...

  6. CocosCreator游戏开发(四)实现摇杆控制角色功能

    时隔3年,我又开始继续写这个系列的帖子了,也不知道是会写完全系列,还是再次夭折. 废话不多.直接开始主题了 主要实现的功能点包含这些内容:通过摇杆控制角色进行八方位移动,并按照各方位播放对应移动动画 ...

  7. Mybatis—curd

    Mybatis简介: MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为 ...

  8. 【独家】React Native 版本升级指南

    前言 React Native 作为一款跨端框架,有一个最让人头疼的问题,那就是版本更新.尤其是遇到大版本更新,JavaScript.iOS 和 Android 三端的配置构建文件都有非常大的变动,有 ...

  9. Linux下非root用户运行Tomcat

    PS:Linux下使用非root用户运行tomcat的原因 由于项目需求,也由于root用户启动tomcat有一个严重的问题,那就是tomcat具有root权限. 这意味着你的任何一个页面脚本(htm ...

  10. [CSP-S2019]树的重心 题解

    CSP-S2 2019 D2T3 考场上扔了T2来打这题的部分分,然后没看到数据范围是等号,不知道怎么判完全二叉树然后40分滚粗…… ---- 思路分析 很容易想到$O(n^2)$每次暴力找重心,这个 ...