tomcat
2022-02-22 17:35:35 0 举报
AI智能生成
tomcat8
作者其他创作
大纲/内容
tomcat
① 源码编译
tomcat8.5.x
在根目录下新建一个pom.xml
将pom.xml 引入到idea,以便idea能够识别
删除TestCookieFilter类
加入VM运行参数-Duser.language=en,防止乱码
在ContextConfig.java的configureStar()方法中加入jsp解析器
context.addServletContainerInitializer(new JasperInitializer(), null);
运行org.apache.catalina.startup.Bootstrap的main方法启动
② 整体架构
连接器:处理socket连接
连接器 - Coyote
协议
传输层(EndPoint)
NIO
NIO2
APR
应用层(Processor)
HTTP
AJP
HTTP2
组件
EndPoint
Processor
ProtocolHandler
Adapter
容器:加载和管理servlet
结构
Catalina-->Server-->List<Service>--->List<Connector>&Container
其中Container-->Engine-->Host--->Context-->Wrapper Servlet
Catalina组件
Catalina
负责解析Tomcat的配置文件,以此来创建服务器Server组件,并根据命令来对其进行管理
Server
服务器表示整个Catalina Servlet容器以及其他组件,负责并启动Servlet引擎,Tomcat连接器。Server通过实现Lifecycle接口,提供了一种优雅的启动和关闭整个系统的方式
Service
服务是Server内部的组件,一个Server包含多个Service。它将若干个Connector组件绑定到一个Container(Engine)上
Connector
连接器,处理与客户端的通信,它负责接收客户请求,然后转给相关的容器处理,最后向客户返回响应结果
Container
容器,负责处理用户的servlet请求,并返回对象给web用户的模块
结构
Engine
表示整个Catalina的Servlet引擎,用来管理多个虚拟站点,一个Service最多只能有一个Engine,但是一个引擎可包含多个Host
Host
代表一个虚拟主机,或者说站点,可以给Tomcat配置多个虚拟主机地址,而一个虚拟主机地址下可包含多个Context
Context
表示一个应用程序,一个应用程序包含多个Wrapper
Wrapper
表示一个Servlet,Wrapper作为容器中的最底层,不能包含子容器
③ 启动流程
入口 org.apache.catalina.startup.Bootstrap.main()
初始化三个类加载器 initClassLoaders();
设置Catalina实例的父级类加载器为sharedLoader(默认情况下就是commonLoader)
catalinaDaemon = startupInstance;
解析server.xml,初始化Catalina daemon.load(args);
调用 Catalina.load()
初始化文件解析器
Digester digester = createStartDigester();
将<Server>节点,解析为一个org.apache.catalina.core.StandardServer对象,
如果配置了className属性,则会解析对应的类对象。
如果配置了className属性,则会解析对应的类对象。
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
"org.apache.catalina.core.StandardServer",
"className");
将<Server>节点中的属性,使用StandardServer对象对应的set方法进行属性初始化
digester.addSetProperties("Server");
将<Server>节点对应的对象,调用<Server>节点的父节点对象的
setServer(org.apache.catalina.Server params)方法,
Server的父对象为this,后面会设置,也就Catalina对象。
setServer(org.apache.catalina.Server params)方法,
Server的父对象为this,后面会设置,也就Catalina对象。
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");
"setServer",
"org.apache.catalina.Server");
创建Connector对象,在里面会初始化executor
digester.addRule("Server/Service/Connector",
new ConnectorCreateRule());
new ConnectorCreateRule());
a. endpoint = new JIoEndpoint();
b. cHandler = new Http11ConnectionHandler(this); //
c. ((JIoEndpoint) endpoint).setHandler(cHandler); // endpoint对应的连接处理器
根据Connector节点的属性,调用set方法进行初始化,除开executor属性。
digester.addRule("Server/Service/Connector",
new SetAllPropertiesRule(new String[]{"executor"}));
new SetAllPropertiesRule(new String[]{"executor"}));
将Connector对象通过调用Service.addConnector方法添加到Service中去,
addConnector方法并不是简单的实现,还有其他逻辑,后面在详细的介绍。
addConnector方法并不是简单的实现,还有其他逻辑,后面在详细的介绍。
digester.addSetNext("Server/Service/Connector",
"addConnector",
"org.apache.catalina.connector.Connector");
"addConnector",
"org.apache.catalina.connector.Connector");
addRuleSet方法实现也不复杂,就是调用NamingRuleSet、
EngineRuleSet这些类的addRuleInstances方法
EngineRuleSet这些类的addRuleInstances方法
digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
...
...
找server.xml文件
1.从文件系统中获取server.xml
file = configFile(); // 获取catalina.base目录下的conf/server.xml文件
2.如果文件系统没有,
则从classloader中获取server.xml
则从classloader中获取server.xml
inputStream = getClass().getClassLoader()
.getResourceAsStream(getConfigFile());
inputSource = new InputSource
(getClass().getClassLoader()
.getResource(getConfigFile()).toString());
.getResourceAsStream(getConfigFile());
inputSource = new InputSource
(getClass().getClassLoader()
.getResource(getConfigFile()).toString());
3.如果没找到server.xml,
那么则从classloader中找server-embed.xml
那么则从classloader中找server-embed.xml
inputStream = getClass().getClassLoader()
.getResourceAsStream("server-embed.xml");
inputSource = new InputSource
(getClass().getClassLoader()
.getResource("server-embed.xml").toString());
.getResourceAsStream("server-embed.xml");
inputSource = new InputSource
(getClass().getClassLoader()
.getResource("server-embed.xml").toString());
解析server.xml或者server-embed.xml
digester.parse(inputSource);
解析完server.xml或server-embed.xml后,
将catalina设置到StandardServer中
将catalina设置到StandardServer中
getServer().setCatalina(this);
解析完配置文件,开始初始化Server,
而从初始化Server开始,
就包括了一系列的子组件的初始化
而从初始化Server开始,
就包括了一系列的子组件的初始化
getServer().init();实际调用了StandardServer.initInternal()
services[i].init();
Service下的容器初始化,默认情况下是StandardEngine
StandardEngine.initInternal()
ContainerBase.initInternal()
初始化线程池
可以在Service下配置定义executor,
默认实现类为org.apache.catalina.core.StandardThreadExecutor
可以在Service下配置定义executor,
默认实现类为org.apache.catalina.core.StandardThreadExecutor
初始化连接器
daemon.start();
Catalina.start()
getServer().start();
StandardService.startInternal()
ContainerBase.startInternal()
异步启动<Context/>节点 StandardContext.startInternal()
解析docBase地址
初始化webappLoader
if (getLoader() == null) {
// Webapp类加载器的父类加载器为Host的ParentClassLoader,最终就是Catalina类的类加载器,其实就是CommonClassLoader
WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
webappLoader.setDelegate(getDelegate());
setLoader(webappLoader);
}
// Webapp类加载器的父类加载器为Host的ParentClassLoader,最终就是Catalina类的类加载器,其实就是CommonClassLoader
WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
webappLoader.setDelegate(getDelegate());
setLoader(webappLoader);
}
解析web.xml
fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);
创建WebXml对象
解析web.xml⽂件内容设置WebXml对象属性
Map<String,ServletDef> servlets
Map<String,String> servletMappings
Map<String,FilterDef> filters
Set<FilterMap> filterMaps
收集ServletContainerInitializers
将WebXML对象中的信息配置到Context对象中
context.addFilterDef(filter);
context.addFilterMap(filterMap);
context.addApplicationListener(listener);
遍历每个ServletDef,⽣成⼀个Wrapper,
context.addChild(wrapper);
context.addChild(wrapper);
调⽤ServletContainerInitializers
启动pipeline
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).start();
}
((Lifecycle) pipeline).start();
}
触发START_EVENT事件,会进行deployApps
setState(LifecycleState.STARTING);
是否需要阻塞,await标记是在通过|
Bootstrap类启动时设置为true的
Bootstrap类启动时设置为true的
if (await) { // true
await(); // 使用ServerSocket来监听shutdown命令来阻塞
stop(); // 如果阻塞被解开,那么开始停止流程
}
await(); // 使用ServerSocket来监听shutdown命令来阻塞
stop(); // 如果阻塞被解开,那么开始停止流程
}
默认通过向8005端口发送shutdown指令会关闭tomcat
④ 请求流程
⑤ 类加载器
初始化位置
org.apache.catalina.startup.Bootstrap.main()---> bootstrap.init();
commonLoader
加载类位置
conf/catalina.properties-->common.loader:
父加载器
appClassLoader
catalinaLoader
配置类位置
conf/catalina.properties-->server.loader:
父加载器
commonLoader
sharedLoader
配置类位置
conf/catalina.properties-->shared.loader
父加载器
commonLoader
0 条评论
下一页