本文参考链接:Qmillet,url:https://www.cnblogs.com/qmillet/p/12552336.html
Tomcat 配置文件:
<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JasperListener" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
Tomcat中最顶层的容器是Server,代表着整个服务器,从上图中可以看出,一个Server可以包含至少一个Service,用于具体提供服务
Service主要包含两个部分:多个Connector和一个Container。一个Container可以有多个Host(虚拟主机),一个Host可以有多个Context。从上图中可以看出 Tomcat 的心脏就是这两个组件,他们的作用如下:
1、Connector用于处理连接相关的事情,并提供Socket与Request和Response相关的转化;
2、Container用于封装和管理Servlet,以及具体处理Request请求;
一个Service只有一个Container,但是可以有多个Connectors。因为一个服务可以有多个连接,如同时提供Http和Https链接,也可以提供向相同协议不同端口的连接。
[1]每一个tomcat都只有一个Server,表示整个服务环境。一个Server中可以有多个Service。Server就掌管着Service的死活。
[2]Service是对外提供服务的,每一个Service中可以有多个Connector和一个Container(Engine)。
[3]Connector主要用来接收请求,解析请求内容,封装request和response,然后将准备好的数据交给Container处理。
[4]Container就是我们经常说的容器,里面可以有多个Host,一个Host表示一个虚拟主机。Container处理完请求之后会将响应内容返回给Connecter,再由Connecter响应客户端。
提升:
Connector的架构: Connector最底层使用的是Socket来进行连接的,Request和Response是按照HTTP协议来封装的,所以Connector同时需要实现TCP/IP协议和HTTP协议!
Container的架构:Container就是一个Engine。Container用于封装和管理Servlet,以及具体处理Request请求。
[1] Engine:Container(容器/引擎),用来管理多个站点,一个Service最多只能有一个Engine.
[2] Host: 虚拟主机,一个Container可以有多个虚拟主机。
[3] Context: 一个应用程序,就是我们平时开发的一个项目,或者说一套web引用程序。
[4] Wrapper: 用来包装Servlet,每一个Wraper都包装着一个Servlet。
Tomcat 的类加载结构:
参考:https://blog.youkuaiyun.com/qq_28956737/article/details/102836431
多个web应用之间不能相互影响;
jsp能够热部署;
web服务器本身使用的类库,不被干扰;
多个web应用能够共享lib;
上半部分的类加载还是和普通的JVM一模一样的,
Bootstrap 引导类加载器 :加载JVM启动所需的类,以及标准扩展类(位于jre/lib/ext下),将JVM前三个类加载器概括到一起了。
System 系统类加载器 :加载tomcat启动的类,比如bootstrap.jar,通常在catalina.bat或者catalina.sh中指定。位于CATALINA_HOME/bin下。
Common 通用类加载器:加载tomcat使用以及应用通用的一些类,位于CATALINA_HOME/lib下,比如servlet-api.jar。
webapp应用类加载器:每个应用在部署后,都会创建一个唯一的类加载器。该类加载器会加载位于 WEB-INF/lib下的jar文件中的class和 WEB-INF/classes下的class文件。
JSP类加载器 :tomcat会为每一个JSP创建一个类加载器。
加载流程:
1 使用bootstrap引导类加载器加载 JVM基本类和扩展类
2 使用system系统类加载器加载 tomcat启动的类
3 使用应用类加载器在WEB-INF/classes中加载
4 使用应用类加载器在WEB-INF/lib中加载
5 使用common类加载器在CATALINA_HOME/lib中加载
打破双亲委托机制的桎梏:线程上下文类加载器
线程上下文类加载器是指的当前线程所用的类加载器,可以通过Thread.currentThread().getContextClassLoader()获得或者设置。
在spring中,他会选择线程上下文类加载器去加载web应用底下的类,如此就打破了双亲委托机制了。
tomcat 为了实现隔离性,没有遵守这个约定,每个webappClassLoader加载自己的目录下的class 文件,不会传递给父类加载器。