一,Catalina启动
接上文,BootStart启动后会启动Catalina的start方法:
public void start() {
//加载服务
if (getServer() == null) {
load();
}
//启动服务
try {
getServer().start();
} catch (LifecycleException e) {
return;
}
// 注册关闭钩子,做一些资源清理处理等。
if (useShutdownHook) {
if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
//监听tomcat关闭事件
if (await) {
await();
stop();
}
}
在代码中我们看到Catalina做了4件事,分别是加载服务配置,启动服务,注册关闭钩子,监听关闭事件。下面我们重点介绍前面2个步骤。
二,Catalina加载配置服务
我们查看load方法:
Catalina
public void load() {
// 初始化命名
initNaming();
// 创建和执行Digester
Digester digester = createStartDigester();
InputSource inputSource = null;
InputStream inputStream = null;
File file = null;
try {
//读取conf/server.xml文件
file = configFile();
inputStream = new FileInputStream(file);
inputSource = new InputSource(file.toURI().toURL().toString());
} catch (Exception e) {
}
...//略,读取配置文件
try {
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource);
} catch (SAXParseException spe) {
} finally {
try {
inputStream.close();
} catch (IOException e) {
// Ignore
}
}
getServer().setCatalina(this);
getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
// 初始化server
try {
getServer().init();
} catch (LifecycleException e) {
}
}
这里我们重点关注createStartDigester()方法,它加载了Server的配置文件。
Catalina
protected Digester createStartDigester() {
long t1=System.currentTimeMillis();
// Initialize the digester
Digester digester = new Digester();
digester.setValidating(false);
digester.setRulesValidation(true);
HashMap<Class<?>, List<String>> fakeAttributes = new HashMap<>();
ArrayList<String> attrs = new ArrayList<>();
attrs.add("className");
fakeAttributes.put(Object.class, attrs);
digester.setFakeAttributes(fakeAttributes);
digester.setUseContextClassLoader(true);
// Configure the actions we will be using
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
digester.addSetProperties("Server");
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");
digester.addObjectCreate("Server/GlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");
digester.addSetProperties("Server/GlobalNamingResources");
digester.addSetNext("Server/GlobalNamingResources",
"setGlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");
digester.addObjectCreate("Server/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Listener");
digester.addSetNext("Server/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
digester.addObjectCreate("Server/Service",
"org.apache.catalina.core.StandardService",
"className");
digester.addSetProperties("Server/Service");
digester.addSetNext("Server/Service",
"addService",
"org.apache.catalina.Service");
digester.addObjectCreate("Server/Service/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Listener");
digester.addSetNext("Server/Service/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
//Executor
digester.addObjectCreate("Server/Service/Executor",
"org.apache.catalina.core.StandardThreadExecutor",
"className");
digester.addSetProperties("Server/Service/Executor");
digester.addSetNext("Server/Service/Executor",
"addExecutor",
"org.apache.catalina.Executor");
digester.addRule("Server/Service/Connector",
new ConnectorCreateRule());
digester.addRule("Server/Service/Connector",
new SetAllPropertiesRule(new String[]{"executor", "sslImplementationName"}));
digester.addSetNext("Server/Service/Connector",
"addConnector",
"org.apache.catalina.connector.Connector");
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig",
"org.apache.tomcat.util.net.SSLHostConfig");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig");
digester.addSetNext("Server/Service/Connector/SSLHostConfig",
"addSslHostConfig",
"org.apache.tomcat.util.net.SSLHostConfig");
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
new CertificateCreateRule());
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
new SetAllPropertiesRule(new String[]{"type"}));
digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate",
"addCertificate",
"org.apache.tomcat.util.net.SSLHostConfigCertificate");
digester.addObjectCreate("Server/Service/Connector/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Connector/Listener");
digester.addSetNext("Server/Service/Connector/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
digester.addObjectCreate("Server/Service/Connector/UpgradeProtocol",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Connector/UpgradeProtocol");
digester.addSetNext("Server/Service/Connector/UpgradeProtocol",
"addUpgradeProtocol",
"org.apache.coyote.UpgradeProtocol");
// Add RuleSets for nested elements
digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
digester.addRuleSet(new EngineRuleSet("Server/Service/"));
digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));
// When the 'engine' is found, set the parentClassLoader.
digester.addRule("Server/Service/Engine",
new SetParentClassLoaderRule(parentClassLoader));
addClusterRuleSet(digester, "Server/Service/Engine/Cluster/");
long t2=System.currentTimeMillis();
if (log.isDebugEnabled()) {
log.debug("Digester for server.xml created " + ( t2-t1 ));
}
return (digester);
}
这个有点长,我们可以看到它其实就是针对Server.xml进行了实例化。它的原理是利用sax的DefaultHandler2来解析各个不同的对象。
三,Lifecycle初始化init方法
当Server实例化之后,接下来就需要调用它的init方法了。我们看到init实现了Lifecycle的init接口。那么Lifecycle是什么呢?从字面意思来看就是生命周期。它有初始化,启动,停止,销毁等状态。容器里的Server,Service,Engine,Host,Context等都有自己的生命周期。
下面我们看看它的init方法。
3.1 LifecycleBase的init
LifecycleBase
public final synchronized void init() throws LifecycleException {
//检查当前状态
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
//生命周期的状态,设置标志位表示当前正在初始化中,状态改变的时候可能会触发监听器做一些事情
setStateInternal(LifecycleState.INITIALIZING, null, false);
try {
initInternal();
} catch (Throwable t) {
}
//生命周期的状态,设置标志位表示当前正在初始化完成
setStateInternal(LifecycleState.INITIALIZED, null, false);
}
3.2 StandardServer的initInternal
我们看initInternal方法:
StandardServer
protected void initInternal() throws LifecycleException {
//初始化Mbean服务并注册mbean
super.initInternal();
//注册命名服务
globalNamingResources.init();
//初始化Service
for (int i = 0; i < services.length; i++) {
services[i].init();
}
}
我们可以看到Server接着又初始化了Service的init方法。
3.3 StandardService的initInternal
StandardService的initInternal主要做的就是初始化Connector和Container。
protected void initInternal() throws LifecycleException {
super.initInternal();
//container初始化
if (container != null) {
container.init();
}
// 初始化Executors
for (Executor executor : findExecutors()) {
if (executor instanceof JmxEnabled) {
((JmxEnabled) executor).setDomain(getDomain());
}
executor.init();
}
// Initialize mapper listener
mapperListener.init();
// Initialize our defined Connectors
synchronized (connectorsLock) {
for (Connector connector : connectors) {
try {
//connector初始化
connector.init();
} catch (Exception e) {
}
}
}
}
我们可以看到,一个Service对于一个Container和多个Connector。
在server.xml文件中。有2个Connector:
server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
他们分别接受Http和Ajp协议。由于Container和Connector的初始化流程太长,放到后面讲。
六,启动服务Server
初始化所有的节点后,接下来就是启动Server了。我们先看Server的start方法。同样的,Server继承了LifecycleBase的start方法。
6.1 Lifecycle的start
LifecycleBase
public final synchronized void start() throws LifecycleException {
if (LifecycleState.STARTING_PREP.equals(state) ||
LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) {
return;
}
if (state.equals(LifecycleState.NEW)) {
init();
} else if (state.equals(LifecycleState.FAILED)){
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}
setStateInternal(LifecycleState.STARTING_PREP, null, false);
try {
startInternal();
} catch (Throwable t) {
}
if (state.equals(LifecycleState.FAILED) ||
state.equals(LifecycleState.MUST_STOP)) {
stop();
} else {
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
if (!state.equals(LifecycleState.STARTING)) {
invalidTransition(Lifecycle.AFTER_START_EVENT);
}
setStateInternal(LifecycleState.STARTED, null, false);
}
}
我们看到start会根据当前的状态做判断,我们只看startInternal方法,由于这个方法是个抽象方法,由之类实现,所以接下来我们看Server的startInternal。
6.2 Server的startInternal
StandardServer
protected void startInternal() throws LifecycleException {
fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING);
globalNamingResources.start();
// Start our defined Services
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}
Server的startInternal方法会启动Service的start方法。同样,会触发Service的startInternal方法。
6.3 Service的startInternal
protected void startInternal() throws LifecycleException {
setState(LifecycleState.STARTING);
// Start our defined Container first
if (container != null) {
synchronized (container) {
container.start();
}
}
synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}
mapperListener.start();
// Start our defined Connectors second
synchronized (connectorsLock) {
for (Connector connector: connectors) {
try {
// If it has already failed, don't try and start it
if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connector), e);
}
}
}
}
同样,在这段代码中,也调用了container和connector的start方法。在接下来的文章中,我将详细介绍container和connector的启动方式。
五,流程图
说了这么多,没图怎么能行呢?下面就是Boostart到Catalina加载的流程图。