一、概述
在阅读源码之前我们需要对各个类的关系有一个清晰的了解,下面就是Engine各个类之间的关系,我们将会按照从上到下的顺序阅读源码。
二、阅读源码
1、Container
(1)注释
Container可以处理请求并给予相应,并且它还支持由流水线组成的阀门。
/** * A <b>Container</b> is an object that can execute requests received from * a client, and return responses based on those requests. A Container may * optionally support a pipeline of Valves that process the request in an * order configured at runtime, by implementing the <b>Pipeline</b> interface * as well. */
(2)方法
这里引出了流水线比较重要。
/**
* Return the Pipeline object that manages the Valves associated with
* this Container.
*
* @return The Pipeline
*/
Pipeline getPipeline();
该方法常用于执行一些周期性的任务例如重载等,使用这个方法可能会重新加载上下文。
/**
* Execute a periodic task, such as reloading, etc. This method will be
* invoked inside the classloading context of this container. Unexpected
* throwables will be caught and logged.
*/
void backgroundProcess();
BackgroundProcessorDelay这个值设置为负时将不会和父类共享线程,而设置为正时将会共享线程并执行周期方法。
/**
* Get the delay between the invocation of the backgroundProcess method on
* this container and its children. Child containers will not be invoked if
* their delay value is positive (which would mean they are using their own
* thread). Setting this to a positive value will cause a thread to be
* spawned. After waiting the specified amount of time, the thread will
* invoke the {@link #backgroundProcess()} method on this container and all
* children with non-positive delay values.
*
* @return The delay between the invocation of the backgroundProcess method
* on this container and its children. A non-positive value
* indicates that background processing will be managed by the
* parent.
*/
int getBackgroundProcessorDelay();
/**
* Set the delay between the invocation of the execute method on this
* container and its children.
*
* @param delay The delay in seconds between the invocation of
* backgroundProcess methods
*/
void setBackgroundProcessorDelay(int delay);
添加子容器和监听器。
void addChild(Container child);
void addContainerListener(ContainerListener listener);
void addPropertyChangeListener(PropertyChangeListener listener);
(2)容器事件
/**
* The ContainerEvent event type sent when a child container is added
* by <code>addChild()</code>.
*/
String ADD_CHILD_EVENT = "addChild";
/**
* The ContainerEvent event type sent when a valve is added
* by <code>addValve()</code>, if this Container supports pipelines.
*/
String ADD_VALVE_EVENT = "addValve";
/**
* The ContainerEvent event type sent when a child container is removed
* by <code>removeChild()</code>.
*/
String REMOVE_CHILD_EVENT = "removeChild";
/**
* The ContainerEvent event type sent when a valve is removed
* by <code>removeValve()</code>, if this Container supports pipelines.
*/
String REMOVE_VALVE_EVENT = "removeValve";
2、Engine
(1)注释
Engine是处理servlet的引擎。
/** * An <b>Engine</b> is a Container that represents the entire Catalina servlet * engine. */
3、ContainerBase
(1)内部类
这个内部类利用了递归的方法执行了周期性事件。
protected class ContainerBackgroundProcessor implements Runnable {
@Override
public void run() {
Throwable t = null;
String unexpectedDeathMessage = sm.getString("containerBase.backgroundProcess.unexpectedThreadDeath",
Thread.currentThread().getName());
try {
while (!threadDone) {
try {
Thread.sleep(backgroundProcessorDelay * 1000L);
} catch (InterruptedException e) {
// Ignore
}
if (!threadDone) {
processChildren(ContainerBase.this);
}
}
} catch (RuntimeException | Error e) {
t = e;
throw e;
} finally {
if (!threadDone) {
log.error(unexpectedDeathMessage, t);
}
}
}
protected void processChildren(Container container) {
ClassLoader originalClassLoader = null;
try {
if (container instanceof Context) {
Loader loader = ((Context) container).getLoader();
// Loader will be null for FailedContext instances
if (loader == null) {
return;
}
// Ensure background processing for Contexts and Wrappers
// is performed under the web app's class loader
originalClassLoader = ((Context) container).bind(false, null);
}
container.backgroundProcess();
Container[] children = container.findChildren();
for (Container child : children) {
if (child.getBackgroundProcessorDelay() <= 0) {
processChildren(child);
}
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("containerBase.backgroundProcess.error"), t);
} finally {
if (container instanceof Context) {
((Context) container).unbind(false, originalClassLoader);
}
}
}
}
4、StandardEngine
(1)方法
构造方法要求需要设置对应的阀门。
public StandardEngine() {
super();
pipeline.setBasic(new StandardEngineValve());
/* Set the jvmRoute using the system property jvmRoute */
try {
setJvmRoute(System.getProperty("jvmRoute"));
} catch (Exception ex) {
log.warn(sm.getString("standardEngine.jvmRouteFail"));
}
// By default, the engine will hold the reloading thread
backgroundProcessorDelay = 10;
}
StandardEngine的开始和结束方法调用了父类的初始化和开始方法,而父类的这些方法使用了线程池。
@Override
protected void initInternal() throws LifecycleException {
// Ensure that a Realm is present before any attempt is made to start
// one. This will create the default NullRealm if necessary.
getRealm();
super.initInternal();
}
@Override
protected synchronized void startInternal() throws LifecycleException {
// Log our server identification information
if (log.isInfoEnabled()) {
log.info(sm.getString("standardEngine.start", ServerInfo.getServerInfo()));
}
// Standard container startup
super.startInternal();
}