Tomcat源码的整体架构解析
声明:本文参考摘抄自:https://www.cnblogs.com/wangrq/p/tomcat-01.html
Tomcat目录结构:
bin目录: 主要是用来存放tomcat的脚本,如startup.sh , shutdown.sh
conf 目录: 下是配置文件
- catalina.policy: Tomcat安全策略文件,控制JVM相关权限,具体可以参考java. security.Permission
- catalina.properties : Tomcat Catalina行为控制配置文件,比如Common ClassLoader
- logging.properties : Tomcat日志配置文件, JDK Logging
- server.xml : Tomcat Server配置文件
- GlobalNamingResources :全局JNDI资源
- context.xml : 全局Context配置文件
- tomcat-users.xml : Tomcat角色配置文件
- web.xml : Servlet标准的web.xml部署文件, Tomcat默认实现部分配置入内:
-
-
org.apache.catalina.servlets.DefaultServlet
-
org.apache.jasper.servlet.JspServlet
-
1 # /bin/startup.sh 启动 2 EXECUTABLE=catalina.sh 3 exec "$PRGDIR"/"$EXECUTABLE" start "$@" 4 # /bin/shutdown.sh 关闭 5 EXECUTABLE=catalina.sh 6 exec "$PRGDIR"/"$EXECUTABLE" stop "$@" 7 # 启动和关闭都是调用 catalina.sh 脚本 8 # /bin/catalina.sh 发现如下2行 9 org.apache.catalina.startup.Bootstrap "$@" start 10 org.apache.catalina.startup.Bootstrap "$@" stop
org.apache.catalina.startup.Bootstrap类是入口类,内部含有main方法,可以以此查看源码
#catalina.properties #限制可以访问的包 package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat. #common类加载器可以加载的lib资源,catalina.base与catalina.home是相同 common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar" server.loader=默认空,公用common.loader shared.loader=默认空,公用common.loader
<!-- server.xml --> <Server port="8005" shutdown="SHUTDOWN"> <Service name="Catalina"> <Executor name="tomcatThreadPool"namePrefix="exec-my"prestartminSpareThreads="true" maxThread="200"maxThreads="500" minSpareThreads="8"maxIdleTime="10000"/> <Connector port="8080"protocol="HTTP/1.1"executor="tomcatThreadPool"connectionTimeout="20000"redirectPort="8443" /> <Engine name="Catalina" defaultHost="localhost"> <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> <!--<Context docBase="D:\myapp" path="/xxx" reloadable="true" />--> </Host> </Engine> </Service> </Server>
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
2、在server.xml文件中配置Context标签
<Context docBase="D:\myapp" path="/xxx" reloadable="true" />
path: 指定访问该Web应用的URL入口
docBase: 指定Web应用的文件路径,可以给定绝对路径,也可以给定相对于<Host>的appBase属性的相对路径。
reloadable: 如果这个属性设为true,tomcat服务器在运行状态下会监视在WEB-INF/classes和WEB-INF/lib目录下class文件的改动,如果监测到有class文件被更新的,服务器会自动重新加载Web应用。
3、独立的Context xml文件配置
在$CATALINA_BASE/conf/[enginename]/[hostname]/ 目录下(默认conf/Catalina/localhost)创建xml文件,文件名就是contextPath
比如创建api.xml,path就是/api, 注意
:想要根目录访问,文件名为
启动过程:
org.apache.catalina.startup.Bootstrap#main()-> bootstrap.init(); daemon.load(args); daemon.start(); org.apache.catalina.startup.Catalina#load()-> digester.parse(server.xml); getServer().init(); # start()->getServer().start(); org.apache.catalina.core.StandardServer#startInternal()-> for:services[i].start(); initInternal():for:services[i].init(); org.apache.catalina.core.StandardService#startInternal() -> engine.start(); for:executor.start(); for:connector.start(); org.apache.catalina.core.StandardEngine#startInternal()-> findChildren().for:executor.submit(new StartChild(children[i]));->FutureTask->StartChild.start() ((Lifecycle) pipeline).start(); threadStart()->new Thread(new ContainerBackgroundProcessor()).start();
核心组件:
1、Server (org.apache.catalina.Server):
2、Service (org.apache.catalina.Service)
Tomcat封装的、对外提供完整的基于组件的web服务,含有Connectors,Container2个核心组件,以及多个功能组件,各个service之间是独立的,共享同一个JVM资源,每个service组件都包含了若干个用于接收客户端消息的connector组件和处理请求的Engine组件.
service组件还包含若干个Executor组件,每个都是一个线程池,他可以为service内所有组件提供线程池执行任务. org.apache.catalina.core.StandardService。
3、Connector
Tomcat 与外部世界的连接器,监听固定端口接收外部请求,传递给 Container,并将Container 处理的结果返回给外部.
org.apache.coyote.http11.Http11AprProtocol // AprEndpoint org.apache.coyote.http11.Http11NioProtocol // NioEndpoint(默认使用的) org.apache.coyote.http11.Http11Nio2Protocol // Nio2Endpoint
4、Container
Catalina,Servlet容器,内部有多层容器组成,用于管理 Servlet 生命周期,调用 servlet 相关方法。
Engine : Servlet 的顶层容器,包含一个或多个 Host 子容器;
Host:虚拟主机,负责 web 应用的部署和 Context 的创建;
Context:Web 应用上下文,包含多个 Wrapper,负责 web 配置的解析、管理所有的 Web 资源;
Wrapper
// 子容器启动过程 org.apache.catalina.core.ContainerBase#startStopExecutor.submit(new StartChild(children[i])) FutureTask->StartChild.start()
// spi @HandlesTypes(WebApplicationInitializer.class)org.apache.catalina.core.StandardContext#startInternal() org.springframework.web.SpringServletContainerInitializer#onStartup() ContextConfig#webConfig() org.apache.catalina.startup.ContextConfig#configureContext() //<load-on-startup>1</load-on-startup> org.apache.catalina.core.StandardContext#loadOnStartup() //servlet 初始化
Spring boot中Tomcat容器和IoC容器的启动顺序
war外置: Tomcat启动带动IoC容器启动
内嵌: Ioc容器带动Tomcat启动
org.springframework.boot.web.embedded.tomcat.TomcatWebServer#start
org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#getWebServer
org.springframework.context.support.AbstractApplicationContext#refresh