Tomcat简单分析-Container
1.Container的有四个子容器,分别是Engine,Host,Context,Wrapper,如下:
2.Container一个也有四个子接口Engine,Host,Context,Wrapper和一个默认实现类ContainerBase,另外这四个子容器都是对应一个StandardXXX实现类,都继承ContainerBase,并且Container还继承LifeCycle接口,所以这四个容器也是符合Tomcat的生命周期模式,结构图如下:
3.解析四个子容器
3.1 Engine:引擎,分别用来管理多个站点,一个Service最多只能有一个Engine
3.2 Host:表示一个站点,通过配置Host可以添加站点
3.3 Context:表示一个应用程序,对应着平时开发对应的一套程序,或者一个WEB-INF目录以及下面的web.xml文件
3.4 Wrapper:每个Wrapper封装一个Servlet
理解Host和Context区别看图:
3.5 四种容器的配置方法
3.5.1 Engine和Host的配置都在conf/server.xml中,默认的server.xml配置文件如下:
<Server port="8005" shutdown="SHUTDOWN"> <!--8005端口监听关闭名利SHUTDOWN-->
<Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<GlobalNamingResources>
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
</GlobalNamingResources>
<Service name="Catalina"> <!--Service服务名Catalina-->
<!--Http协议的connector-->
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
<!--AJP协议的端口-->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
<!--默认的Host即localhost-->
<Engine defaultHost="localhost" name="Catalina">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
<!--appBase就是我们定义的站点webapps,autoDeploy 为true表示自动部署,unpachWAR为true表示自动解压WAR文件-->
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt"/>
<!--这是我自己的一个Metting项目-->
<Context docBase="E:\apache-tomcat-9.0.4\webapps\Metting-Web" path="/Metting-Web" reloadable="true" source="org.eclipse.jst.jee.server:Metting-Web"/></Host>
</Engine>
</Service>
</Server>
另外Host还有一个Alias子标签,可以通过域名访问同一个站点可以这样定义,比如www.visonws.com和visonws.com访问同意站点可以:
<Host name="www.visonws.com" appBase="/webapps" unpackWARS="true" autoDeploy="true">
<Alias>visonws.com</Alias>
</Host>
Engine在定义的时候有一个defaultHost属性,他表示如果在Host的name和Alias都找不到时就是用默认的Host.
3.5.2 Context有三种配置,
I:通过文件配置,
II:将WAR应用直接放到Host目录下去,Tomcat会自动查找并添加到Host中
III:将应用的文件夹放到Host目录下,Tomcat也会自动查找添加到Host中
通过文件配置有五个地方配置:
1>:conf/server.xml文件的Context标签
2>:conf/[enginename]/[hostname]/目录下以应用命名的xml文件
3>:应用自己的/META-INF/context.xml文件
前三个用于配置单独的应用,另外conf/server.xml只有在Tomcat重启时候重新加载
4>:conf/context.xml文件 ,这个是在Tomcat*享
5>::conf/[enginename]/[hostname]/context.xml.default文件,这个实在对应的站点共享
3.5.3 Wrapper的配置就是我们再web.xml中的配置Servlet,一个Servlet对应一个Wrapper,另外也可以在conf/web.xml文件配置全局的Wrapper,处理Jsp的JspServlet就是配置在这里,所以不用自己配置JspServlet就可以处理Jsp请求了。
4. Container的启动
4.1 ContainerBase, 四个容器有一个共同的父类ContainerBase,这个父类包含initInternal和startInternal方法。
initInternal方法用来初始化ThreadPoolExecutor类型的startStopExecutor属性,用于启动和关闭线程。
startInternal方法主要做了五件事:
1>:如果有Cluster和Realm则调用了start方法(Cluster用于配置集群,他的作用是同步Session,Realm是Tomcat的安全域,可以 用来管理资源的访问权限,server.xml中有注释的参考配置)
2>:调用所有子容器的start方法启动子容器,子容器Future是阻塞的,所以只有在子容器全部启动完了,才启动管道Valve
3>:调用管道中Valve的start方法启动管道
4>:启动完成后将生命周期状态设置为LifeCycleState.STARTING
5>:启动后台程序定时处理一些事情,后台线程是一个while循环,内部会定期调用 backgroundProcess做一些事情。
backgroundProcess方法在Container接口中有一个方法,一共有三个实现,分别在ContainerBase,StandardContext和StandardWrapper中,
ContainerBase提供了所有容器共同的处理过程。
StandardContext的backgroundProcess除了处理自己的相关业务,还对Session过期和资源变化进行了处理
StandardWrapper的backgroundProcess除了处理自己的相关业务,会对Jsp生成的Servlet定期进行检查
4.2 Engine 他的默认实现类是StandardEngine,它里面的方法有initInternal和startInternal
4.3 Host 默认实现类StandardHost,初始化默认调用ContainerBase的initInternal方法,有startInternal方法,还有HostConfig方法,可以简单地做日志记录,HostConfig中的start方法会检查配置的Host站点配置的位置是否存在以及是不是目录,最后调用deployApps方法部署应用,有三种方式部署,XML描述文件,WAR文件和文件夹部署。
看源代码:
protected void deployApps(String name) {
File appBase = this.host.getAppBaseFile();
File configBase = this.host.getConfigBaseFile();
ContextName cn = new ContextName(name, false);
String baseName = cn.getBaseName();
if (!this.deploymentExists(cn.getName())) {
File xml = new File(configBase, baseName + ".xml");
if (xml.exists()) {
this.deployDescriptor(cn, xml);
} else {
File war = new File(appBase, baseName + ".war");
if (war.exists()) {
this.deployWAR(cn, war);
} else {
File dir = new File(appBase, baseName);
if (dir.exists()) {
this.deployDirectory(cn, dir);
}
}
}
}
}
4.4 Context 他的默认实现类是StandardContext在startInternal中调用了web.xml中的Listener,另外还初始化了启动的Filter和load-on-startup的Servlet. Context和Host一样也有一个LifecycleLIstener类型的监听器ContextConfig,configureStart防范用来处理CONFIGURE_START_EVENT事件,这个方法调用webConfig方法,webConfig解析web.xml文件,相应的创建了Wrapper并使用gaddChild添加到了Context里面。
4.5 Wrapper 他的默认实现类是StandardWrapper,初始化默认调用ContainerBase的initInternal方法,有自己的startInternal方法。
上一篇: IDEA配置GIT
下一篇: tomcat项目部署去掉项目名