一、Tomcat生命周期的管理
Tomcat通过package org.apache.catalina.Lifecycle;接口管理Tomcat的生命周期。
package org.apache.catalina;
public interface Lifecycle {
//定义的String常量,用于LifecycleEvent事件的type属性中,作用是区分组件发出的LifecycleEvent事件时的状态(如初始化前,启动前,启动中等)
public static final String BEFORE_INIT_EVENT = "before_init";
public static final String AFTER_INIT_EVENT = "after_init";
public static final String START_EVENT = "start";
public static final String BEFORE_START_EVENT = "before_start";
public static final String AFTER_START_EVENT = "after_start";
public static final String STOP_EVENT = "stop";
public static final String BEFORE_STOP_EVENT = "before_stop";
public static final String AFTER_STOP_EVENT = "after_stop";
public static final String AFTER_DESTROY_EVENT = "after_destroy";
public static final String BEFORE_DESTROY_EVENT = "before_destroy";
public static final String PERIODIC_EVENT = "periodic";
public static final String CONFIGURE_START_EVENT = "configure_start";
public static final String CONFIGURE_STOP_EVENT = "configure_stop";
public void addLifecycleListener(LifecycleListener listener); //添加LifecycleListener
//监听器
public LifecycleListener[] findLifecycleListeners();
public void init() throws LifecycleException;
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
public void destroy() throws LifecycleException;
public LifecycleState getState();
public String getStateName();
public interface SingleUse {
}
}
所有生命周期的组件都要实现Lifecycle接口。
LifecycleBase是Lifecycle的默认实现。Server,Service等生命周期组件直接或间接继承了LifecycleBase;
LifecycleBase里面定义了一个 LifecycleSupport类来管理监听器。
/**
* Used to handle firing lifecycle events.
* TODO: Consider merging LifecycleSupport into this class.
*/
private final LifecycleSupport lifecycle = new LifecycleSupport(this);
LifecycleSupport代码如下:
/**
* Support class to assist in firing LifecycleEvent notifications to
* registered LifecycleListeners.
*
* @author Craig R. McClanahan
*/
public final class LifecycleSupport {
// ----------------------------------------------------------- Constructors
/**
* Construct a new LifecycleSupport object associated with the specified
* Lifecycle component.
*
* @param lifecycle The Lifecycle component that will be the source
* of events that we fire
*/
public LifecycleSupport(Lifecycle lifecycle) {
super();
this.lifecycle = lifecycle;
}
// ----------------------------------------------------- Instance Variables
/**
* The source component for lifecycle events that we will fire.
*/
private final Lifecycle lifecycle;
/**
* The list of registered LifecycleListeners for event notifications.
*/
private final List<LifecycleListener> listeners = new CopyOnWriteArrayList<>();
// --------------------------------------------------------- Public Methods
/**
* Add a lifecycle event listener to this component.
*
* @param listener The listener to add
*/
public void addLifecycleListener(LifecycleListener listener) {
listeners.add(listener);
}
/**
* Get the lifecycle listeners associated with this lifecycle. If this
* Lifecycle has no listeners registered, a zero-length array is returned.
*/
public LifecycleListener[] findLifecycleListeners() {
return listeners.toArray(new LifecycleListener[0]);
}
/**
* Notify all lifecycle event listeners that a particular event has
* occurred for this Container. The default implementation performs
* this notification synchronously using the calling thread.
*
* @param type Event type
* @param data Event data
*/
public void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
for (LifecycleListener listener : listeners) {
listener.lifecycleEvent(event);
}
}
/**
* Remove a lifecycle event listener from this component.
*
* @param listener The listener to remove
*/
public void removeLifecycleListener(LifecycleListener listener) {
listeners.remove(listener);
}
}
而在LifecycleSupport类里面定义了一个LifecycleListener集合类型来保存LifecycleListener监听器。
代码如下:
/**
* Support class to assist in firing LifecycleEvent notifications to
* registered LifecycleListeners.
*
* @author Craig R. McClanahan
*/
public final class LifecycleSupport {
// ----------------------------------------------------------- Constructors
/**
* Construct a new LifecycleSupport object associated with the specified
* Lifecycle component.
*
* @param lifecycle The Lifecycle component that will be the source
* of events that we fire
*/
public LifecycleSupport(Lifecycle lifecycle) {
super();
this.lifecycle = lifecycle;
}
// ----------------------------------------------------- Instance Variables
/**
* The source component for lifecycle events that we will fire.
*/
private final Lifecycle lifecycle;
/**
* The list of registered LifecycleListeners for event notifications.
*/
private final List<LifecycleListener> listeners = new CopyOnWriteArrayList<>();
// --------------------------------------------------------- Public Methods
/**
* Add a lifecycle event listener to this component.
*
* @param listener The listener to add
*/
public void addLifecycleListener(LifecycleListener listener) {
listeners.add(listener);
}
/**
* Get the lifecycle listeners associated with this lifecycle. If this
* Lifecycle has no listeners registered, a zero-length array is returned.
*/
public LifecycleListener[] findLifecycleListeners() {
return listeners.toArray(new LifecycleListener[0]);
}
/**
* Notify all lifecycle event listeners that a particular event has
* occurred for this Container. The default implementation performs
* this notification synchronously using the calling thread.
*
* @param type Event type
* @param data Event data
*/
public void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
for (LifecycleListener listener : listeners) {
listener.lifecycleEvent(event);
}
}
/**
* Remove a lifecycle event listener from this component.
*
* @param listener The listener to remove
*/
public void removeLifecycleListener(LifecycleListener listener) {
listeners.remove(listener);
}
}
LifecycleListener类代码如下:
/**
* Interface defining a listener for significant events (including "component
* start" and "component stop" generated by a component that implements the
* Lifecycle interface. The listener will be fired after the associated state
* change has taken place.
*
* @author Craig R. McClanahan
*/
public interface LifecycleListener {
/**
* Acknowledge the occurrence of the specified event.
*
* @param event LifecycleEvent that has occurred
*/
public void lifecycleEvent(LifecycleEvent event);
}
二、 LifecycleBase类的生命周期方法分析:
四个生命周期方法分别是 init(),start(),stop(),destroy()方法。都会线判断状态和当前方法是否匹配。
如在init方法之前调用了start方法。这时会先执行init方法。
LifecycleBase的状态是通过LifecycleBase类型的state属性来保存的,最开始初始化值为LifecycleState.NEW.
initInternal()和startInternal()模板方法会调用具体的子类具体来启动。
LifecycleBase类的init方法代码如下:
@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {//如果状态不是NEW,就
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
try { //初始化前将状态设置为LifecycleState.INITIALIZING
setStateInternal(LifecycleState.INITIALIZING, null, false);
initInternal(); //具体执行初始化
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.initFail",toString()), t);
}
}
protected abstract void initInternal() throws LifecycleException;
//invalidTransition 抛出LifecycleException异常
//处理不符合要求的状态
private void invalidTransition(String type) throws LifecycleException {
String msg = sm.getString("lifecycleBase.invalidTransition", type,
toString(), state);
throw new LifecycleException(msg);
}
private synchronized void setStateInternal(LifecycleState state,
Object data, boolean check) throws LifecycleException {
if (log.isDebugEnabled()) {
log.debug(sm.getString("lifecycleBase.setState", this, state));
}
if (check) { //check 该段主要是校验state状态,state为null抛出异常,
//state不是FAILED 并且state不是STARTING或者this.state不是STARTING_PREP 或state不是STARTING,this.state也不是STARTING_PREP (省略。。)才会抛出异常,无法识别得到state.
//state可以是FAILED
//state可以是STARTING,this.state可以是STARTING_PREP
//state可以是STOPPING,this.state可以是STOPPING_PREP
//state可以是STOPPING,this.state可以是FAILED 都不会进入异常
// Must have been triggered by one of the abstract methods (assume
// code in this class is correct)
// null is never a valid state
if (state == null) {
invalidTransition("null");
// Unreachable code - here to stop eclipse complaining about
// a possible NPE further down the method
return;
}
// Any method can transition to failed
// startInternal() permits STARTING_PREP to STARTING
// stopInternal() permits STOPPING_PREP to STOPPING and FAILED to
// STOPPING
if (!(
state == LifecycleState.FAILED ||
(this.state == LifecycleState.STARTING_PREP &&
state == LifecycleState.STARTING) ||
(this.state == LifecycleState.STOPPING_PREP &&
state == LifecycleState.STOPPING) ||
(this.state == LifecycleState.FAILED &&
state == LifecycleState.STOPPING)
)) {
// No other transition permitted
invalidTransition(state.name());
}
}
this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data); //处理事件
}
}
setStateInternal()方法中通过check参数来判断是否需要检查传入的状态state.如果需要检查则会检查传入的状态是否为空和是否符合正确的状态,最后设置state.
LifecycleBase类的start方法代码如下:
/**
* {@inheritDoc}
*/
@Override
public final synchronized void start() throws LifecycleException {
//检查状态是否已经启动,如果已经启动打印log
if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
}
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);
}
try {
setStateInternal(LifecycleState.STARTING_PREP, null, false);
startInternal();
if (state.equals(LifecycleState.FAILED)) {
// This is a 'controlled' failure. The component put itself into the
// FAILED state so call stop() to complete the clean-up.
stop();
} else if (!state.equals(LifecycleState.STARTING)) {//如果启动后状态不是
//STARTING则抛出异常
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
//启动成功后将状态设为STARTED
setStateInternal(LifecycleState.STARTED, null, false);
}
} catch (Throwable t) {
// This is an 'uncontrolled' failure so put the component into the
// FAILED state and throw an exception.
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
}
}
三、Container源码分析
Container的作用是具体负责处理Servlet,处理Http请求。
public interface Container extends Lifecycle {
Container 四个子容器 Engine,Host,Context,Wrapper逐层包含的关系。
Engine 引擎,用来管理多个站点。
Host 站点(虚拟主机),整个webapps是一个站点,如:www.test.com域名对应webapps目录所代表的站点,其中ROOT目录 是主应用,直接使用域名就可以访问主应用。而webapps/test是test子应用,访问www.test.com/test
Context 应用程序,默认配置下webapps下的每个目录都市一个应用。其中ROOT目录存放着主应用,其他目录是子应用。
Wrapper 每个Wrapper封装一个Servlet.
配置:
Server.xml文件里面放了Tomcat大部分功能的配置。
Server.xml文件默认配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JasperListener"/>
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<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">
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
<Engine defaultHost="localhost" name="Catalina">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Valve className="org.apache.catalina.valv