转JAVA开发(之前做.NET(C#))到现在已经一年多一点了。掌握了基本JAVA开发技能,但对于JAVA更深层次的基数一直无暇探究。今天开始就来着手从Tomcat9源代码开始研究JAVA的世界。
本系列文章是本人针对Tomcat9的部分源代码个人理解的一个归纳,如有不正确的地方请及时纠正。本人邮箱:249466389@qq.com欢迎大家一起研究讨论。
准备工作
- 开发工具:IDEA
- Tomcat源代码版本:apache-tomcat-9.0.2-src
- 下载地址:https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.2/src/apache-tomcat-9.0.2-src.zip
- SSH工具:Bitvise SSH Client
Tomcat安装方法此处不再赘述,不会的同学可以找度娘。
正文
当我们一套系统开发完毕,将打好*.war包丢到/Tomcat/webapp/目录下,调用/Tomcat/bin/startup.sh启动系统。此时Tomcat服务开始启动。本系列文章就从此处作为入口结合Tomcat源代码一起进入Tomcat的世界,看看她是如何实现,如何工作。
既然从startup.sh开始,我们就首先来看看startup.sh做了些什么
[root@localhost ~]# cd /home/tomcat/bin/
[root@localhost bin]# vi startup.sh
代码1
通过上面命令我们可以得到看到如下内容
-----上面内容自动忽略-----
//注册该文件为一个可执行文件(脚本)
os400=false
case "`uname`" in
OS400*) os400=true;;
esac
//解析连接地址是否软连接
PRG="$0"
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
done
//当前路径
PRGDIR=`dirname "$PRG"`
//文件名称
EXECUTABLE=catalina.sh
//检查目标可执行文件是否存在
if $os400; then
# -x will Only work on the os400 if the files are:
# 1. owned by the user
# 2. owned by the PRIMARY group of the user
# this will not work if the user belongs in secondary groups
eval
else
if [ ! -x "$PRGDIR"/"$EXECUTABLE" ]; then
echo "Cannot find $PRGDIR/$EXECUTABLE"
echo "The file is absent or does not have execute permission"
echo "This file is needed to run this program"
exit 1
fi
fi
//执行文件
exec "$PRGDIR"/"$EXECUTABLE" start "$@"
代码2
通过代码2中的内容我们可以看出,startup.sh的执行步骤:
- 对当前的操作系统进行检测,检测完毕后验证连接是否可用。
- 定义变量:PRGDIR存储当前系统目录,EXECUTABLE存储文件名称
- 调用另外一个可执行文件(shell脚本)`catalina.sh`。并传递参数`start`
[root@localhost bin]# ls
[root@localhost bin]# vi catalina.sh
代码4
执行上面的命令后,我们可以看到`catalina.sh`内容。
if [ "$1" = "debug" ] ; then
-------忽略部分-----------
exec "$_RUNJDB" "$LOGGING_CONFIG" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath "$CLASSPATH" \
-sourcepath "$CATALINA_HOME"/../../java \
-Djava.security.manager \
-Djava.security.policy=="$CATALINA_BASE"/conf/catalina.policy \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMPDIR" \
org.apache.catalina.startup.Bootstrap "$@" start
else
exec "$_RUNJDB" "$LOGGING_CONFIG" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -classpath "$CLASSPATH" \
-sourcepath "$CATALINA_HOME"/../../java \
-Dcatalina.base="$CATALINA_BASE" \
-Dcatalina.home="$CATALINA_HOME" \
-Djava.io.tmpdir="$CATALINA_TMPDIR" \
org.apache.catalina.startup.Bootstrap "$@" start
fi
fi
elif [ "$1" = "run" ]; then
-------忽略部分-----------
eval exec "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
-Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start
else
eval exec "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start
fi
elif [ "$1" = "start" ] ; then
-------忽略部分-----------
eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
-Djava.security.manager \
-Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
>> "$CATALINA_OUT" 2>&1 "&"
else
eval $_NOHUP "\"$_RUNJAVA\"" "\"$LOGGING_CONFIG\"" $LOGGING_MANAGER $JAVA_OPTS $CATALINA_OPTS \
-Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" start \
>> "$CATALINA_OUT" 2>&1 "&"
fi
-------忽略部分-----------
代码5-1
elif [ "$1" = "stop" ] ; then
-------忽略部分-----------
eval "\"$_RUNJAVA\"" $LOGGING_MANAGER $JAVA_OPTS \
-Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap "$@" stop
代码5-2
elif [ "$1" = "configtest" ] ; then
-------忽略部分-----------
eval "\"$_RUNJAVA\"" $LOGGING_MANAGER $JAVA_OPTS \
-Djava.endorsed.dirs="\"$JAVA_ENDORSED_DIRS\"" -classpath "\"$CLASSPATH\"" \
-Dcatalina.base="\"$CATALINA_BASE\"" \
-Dcatalina.home="\"$CATALINA_HOME\"" \
-Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
org.apache.catalina.startup.Bootstrap configtest
代码5-3
elif [ "$1" = "version" ] ; then
-------忽略部分-----------
-classpath "$CATALINA_HOME/lib/catalina.jar" \
org.apache.catalina.util.ServerInfo
代码5-4
- 观察代码5-1~5-4我们可以看出来catalina.sh文件的执行步骤如下
- 系统参数验证,就是大家常用的环境变量(JAVA_HOME,,JAR_HOME,CLASSPATH等)的获取。及其他系统变量的获取及验证。根据传递过来的参数(“$1”)调用JAVA文件及方法:
- debug,run,start:调用org.apache.catalina.startup.Bootstrap 传递参数“start”
- stop:调用org.apache.catalina.startup.Bootstrap 传递参数“stop”
- configtest:调用org.apache.catalina.startup.Bootstrap 传递参数“configtest”
- version:调用org.apache.catalina.util.ServerInfo