1 Container容器
Container容器用来表示tomcat中servlet容器,负责servelt的加载和管理,处理请求,并返回标准的 ServletResponse 对象给连接器。
imageContainer容器组件
tomcat 将Container容器按功能分为4个组件,分别是 Engine、Host、Context 和 Wrapper。这 4 种容器不是平行关系,而是父子关系。
-
Wrapper:表示一个 Servlet
-
Context:表示一个 Web 应用程序,一个 Web 应用程序中可能会有多个 Servlet
-
Host:表示的是一个虚拟主机,或者说一个站点,可以给 Tomcat 配置多个虚拟主机地址,而一个虚拟主机下可以部署多个 Web 应用程序
-
Engine:表示引擎,用来管理多个虚拟站点,一个 Service 最多只能有一个 Engine。
2 StandardEngine类结构
image2.1 Lifecycle接口
public interface Lifecycle {
....
// 初始化方法
public void init() throws LifecycleException;
// 启动方法
public void start() throws LifecycleException;
// 停止方法,和start对应
public void stop() throws LifecycleException;
// 销毁方法,和init对应
public void destroy() throws LifecycleException;
// 获取生命周期状态
public LifecycleState getState();
// 获取字符串类型的生命周期状态
public String getStateName();
}
Lifecycle接口定义tomcat中所有组件的生命周期相关接口方法。Tomcat 定义一个基类LifecycleBase 来实现 Lifecycle 接口,把一些公共的逻辑放到基类中实现。而子类就负责实现自己的初始化、启动和停止等模板方法。
详见 Tomcat架构设计-组件生命周期 Lifecycle
2.2 Container接口
public interface Container extends Lifecycle {
public static final String ADD_CHILD_EVENT = "addChild";
public static final String ADD_VALVE_EVENT = "addValve";
public static final String REMOVE_CHILD_EVENT = "removeChild";
public static final String REMOVE_VALVE_EVENT = "removeValve";
//返回日志组件
public Log getLogger();
//返回日志名称
public String getLogName();
//返回容器注册到JMX bean ObjectName
public ObjectName getObjectName();
//返回容器注册到JMX bean 命名空间
public String getDomain();
//返回容器注册到JMX bean 属性
public String getMBeanKeyProperties();
//返回容器依赖Pipeline组件
public Pipeline getPipeline();
//返回容器依赖Cluster组件
public Cluster getCluster();
//设置容器依赖Cluster组件
public void setCluster(Cluster cluster);
//返回周期性任务执行间隔事件
public int getBackgroundProcessorDelay();
//设置周期性任务执行间隔事件
public void setBackgroundProcessorDelay(int delay);
//返回容器名称
public String getName();
//设置容器名称
public void setName(String name);
//返回父容器
public Container getParent();
//设置父容器
public void setParent(Container container);
//返回父类加载器
public ClassLoader getParentClassLoader();
//设置父类加载器
public void setParentClassLoader(ClassLoader parent);
//返回容器依赖Realm组件
public Realm getRealm();
// 设置容器依赖Realm组件
public void setRealm(Realm realm);
//容器默认周期性任务处理调用方法
public void backgroundProcess();
//为当前容器组件添加子容器组件
public void addChild(Container child);
//添加容器事件监听器
public void addContainerListener(ContainerListener listener);
//添加属性变更监听器
public void addPropertyChangeListener(PropertyChangeListener listener);
//查找指定名称的子容器
public Container findChild(String name);
//获取所有子容器组件
public Container[] findChildren();
//返回所有容器事件监听器
public ContainerListener[] findContainerListeners();
//删除子容器
public void removeChild(Container child);
//当前容器删除容器事件监听器
public void removeContainerListener(ContainerListener listener);
//当前容器删除属性变更监听器
public void removePropertyChangeListener(PropertyChangeListener listener);
//处理容器事件
public void fireContainerEvent(String type, Object data);
//使用AccessLog组件打印请求日志
public void logAccess(Request request, Response response, long time,
boolean useDefault);
//返回访问日志组件AccessLog
public AccessLog getAccessLog();
//返回设置处理子容器启动关闭线程池核心线程数。
public int getStartStopThreads();
//设置处理子容器启动关闭线程池核心线程数。
public void setStartStopThreads(int startStopThreads);
//返回tomcat工作目录
public File getCatalinaBase();
//返回tomcat安装目录
public File getCatalinaHome();
}
Container接口定义tomcat中所有容器组件的通用接口方法。Tomcat 定义一个基类ContainerBase 来实现Container 接口,把一些公共的逻辑放到基类中实现。
详见 Tomcat架构设计-容器组件基类 ContainerBase
3 StandardEngine职责&核心属性
3.1 职责
StandardEngine核心职责实现Engine接口,并管理子容器Host组件(下图蓝色),以及从父类ContainerBase(下图红色),LifecycleBase(下图黄色) 继承的通用组件。
imagepublic interface Engine extends Container {
//获取默认host组件名称
public String getDefaultHost();
//设置默认host组件名称
public void setDefaultHost(String defaultHost);
//获取Tomcat实例的JVM路由ID。所有路由ID必须唯一
public String getJvmRoute();
//设置Tomcat实例的JVM路由ID。所有路由ID必须唯一
public void setJvmRoute(String jvmRouteId);
//返回关联上层组件Service
public Service getService();
//设置关联上层组件Service
public void setService(Service service);
}
3.2 核心属性
StandardEngine内部只定义实现Engine接口所需要的属性。
public class StandardEngine extends ContainerBase implements Engine {
//默认host子组件名称
private String defaultHost = null;
//上层Service组件
private Service service = null;
//Tomcat实例的JVM路由ID。所有路由ID必须唯一,用于集群环境中
private String jvmRouteId;
...省略代码
其主要属性从ContainerBase继承而来
public abstract class ContainerBase extends LifecycleMBeanBase
implements Container {
...省略代码
/**
* 当前容器的名称
*/
protected String name = null;
/**
* 当前容器组件的父容器组件
*/
protected Container parent = null;
/**
* 父类加载器
*/
protected ClassLoader parentClassLoader = null;
/**
* 存储子容器的Map,key表示容器的名称,value表示容器组件对象
*/
protected final HashMap<String, Container> children = new HashMap<>();
/**
* 容器事件监听器
*/
protected final List<ContainerListener> listeners = new CopyOnWriteArrayList<>();
/**
* log组件
*/
protected Log logger = null;
/**
* 关联的log名称
*/
protected String logName = null;
/**
* 当前容器组件对应cluster组件
*/
protected Cluster cluster = null;
/**
* 集群对象CLuster读写锁
*/
private final ReadWriteLock clusterLock = new ReentrantReadWriteLock();
/**
* 当前容器组件对应的的Realm组件
*/
private volatile Realm realm = null;
/**
* 当前容器组件对应的Realm组件读写锁
*/
private final ReadWriteLock realmLock = new ReentrantReadWriteLock();
/**
* 当前容器组件对应的pipeline组件
*/
protected final Pipeline pipeline = new StandardPipeline(this);
/**
* 当前容器组件对应的AccessLog组件
*/
protected volatile AccessLog accessLog = null;
/**
* 获取AccessLog组件时
* 如果accessLogScanComplete为false
* 对AccessLog组件初始化(扫描pipeline组件中类型为AccessLog的Value,添加到AccessLog组件)
*/
private volatile boolean accessLogScanComplete = false;
//工具类
/**
* 错误日志管理器
*/
protected static final StringManager sm =
StringManager.getManager(Constants.Package);
/**
* 属性变更处理器
*/
protected final PropertyChangeSupport support =
new PropertyChangeSupport(this);
...省略代码
4 StandardEngine运行流程
tomcat中所有组件都需要经历如下流程。
[图片上传失败...(image-43b823-1565851092609)]
4.1 构建StandardEngine
Tomcat使用Digester解析server.xml,Digester是一款用于将xml转换为Java对象的事件驱动型工具,是对SAX的高层次的封装。相对于SAX,Digester可以针对每一个xml标签设置对应的解析规则。详见 Tomcat相关技术-Digester(二)
Tomcat在Catalina组件初始化阶段调用createStartDigester()创建Digester对象,Digester对象内包含解析server.xml规则,接着通过Digester对象解析server.xml实例化StandardEngine,并对部分属性设置值.
server.xml配置
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
解析<Engine>标签及子标签tomcat在2个规则组EngineRuleSet,HostRuleSet中定义了解析规则。
//设置EngineRuleSet作为解析规则组, 解析<Server><Service>子标签
digester.addRuleSet(new EngineRuleSet("Server/Service/"));
//设置HostRuleSet作为解析规则组.解析<Server><Service><Engine>子标签
digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
4.1 EngineRuleSet规则组
4.1.1 解析<Engine>标签
/** 解析<Engine>标签实例化StandardEngine对象,并push到操作栈中 **/
digester.addObjectCreate(prefix + "Engine",
"org.apache.catalina.core.StandardEngine",
"className");
/** 解析<Engine>标签将标签中属性值映射到其实例化对象中**/
digester.addSetProperties(prefix + "Engine");
/** 解析<Engine>标签将操作栈栈顶对象作为次栈顶对象StandardService.setContainer方法调用的参数,设置到StandardServer.container属性中**/
digester.addSetNext(prefix + "Engine",
"setContainer",
"org.apache.catalina.Engine");
/** 解析<Engine>标签,使用LifecycleListenerRule规则,负责给栈顶对象添加一个生命周期监听器. 默认listenerClass为engineConfigClass,
* 或者在标签指定org.apache.catalina.startup.EngineConfig属性值作为listenerClass**/
digester.addRule(prefix + "Engine",
new LifecycleListenerRule
("org.apache.catalina.startup.EngineConfig",
"engineConfigClass"));
实例化StandardEngine
/**
* 实例化StandardEngine
*/
public StandardEngine() {
super();
/** 设置StandardEngineValve作为pipeline组件尾阀门 **/
pipeline.setBasic(new StandardEngineValve());
/** 从系统属性jvmRoute值,设置 Tomcat实例的JVM路由ID **/
try {
setJvmRoute(System.getProperty("jvmRoute"));
} catch(Exception ex) {
log.warn(sm.getString("standardEngine.jvmRouteFail"));
}
/** 设置周期任务执行间隔事件 **/
backgroundProcessorDelay = 10;
}
设置标签属性映射到StandardEngine对象
<Engine>标签中属性可以查看官方文档 /docs/config/host.htm,这里所有属性在上面的属性中都有说明。
4.1.2 解析<Cluster>标签
//解析<Server><Service><Engine><Cluster>标签
/** 解析<Cluster>标签实例化标签中className属性定义的对象,并push到操作栈中 **/
digester.addObjectCreate(prefix + "Engine/Cluster",
null, // MUST be specified in the element
"className");
/** 解析<Cluster>标签将标签中属性值映射到其实例化对象中**/
digester.addSetProperties(prefix + "Engine/Cluster");
/** 解析<Cluster>标签将操作栈栈顶对象作为次栈顶对象StandardEngine.setCluster方法调用的参数,即设置到StandardEngine.cluster属性中**/
digester.addSetNext(prefix + "Engine/Cluster",
"setCluster",
"org.apache.catalina.Cluster");
设置cluster组件
setCluster()方法是从父类ContainerBase继承.
public abstract class ContainerBase extends LifecycleMBeanBase
implements Container {
...省略代码
@Override
public void setCluster(Cluster cluster) {
Cluster oldCluster = null;
Lock writeLock = clusterLock.writeLock();
writeLock.lock();
try {
/** 获取当前组件原始Cluster组件对象引用设置给oldCluster **/
oldCluster = this.cluster;
if (oldCluster == cluster)
return;
this.cluster = cluster;
/** 如果当前组件还在运行,则停止oldCluster组件 **/
if (getState().isAvailable() && (oldCluster != null) &&
(oldCluster instanceof Lifecycle)) {
try {
((Lifecycle) oldCluster).stop();
} catch (LifecycleException e) {
log.error("ContainerBase.setCluster: stop: ", e);
}
}
/** 将新设置cluster组件和当前容器组件对象反相关联 **/
if (cluster != null)
cluster.setContainer(this);
/** 如果当前组件处于运行状态,启动新设置cluster组件 **/
if (getState().isAvailable() && (cluster != null) &&
(cluster instanceof Lifecycle)) {
try {
((Lifecycle) cluster).start();
} catch (LifecycleException e) {
log.error("ContainerBase.setCluster: start: ", e);
}
}
} finally {
writeLock.unlock();
}
/** 触发属性变更 **/
support.firePropertyChange("cluster", oldCluster, cluster);
}
4.1.3 解析<Listener>标签
//解析<Server><Service><Engine><Listener>标签
/** 解析<Listener>标签实例化标签中className属性定义的对象,并push到操作栈中 **/
digester.addObjectCreate(prefix + "Engine/Listener",
null, // MUST be specified in the element
"className");
/** 解析<Listener>标签将标签中属性值映射到其实例化对象中**/
digester.addSetProperties(prefix + "Engine/Listener");
/** 解析<Cluster>标签将操作栈栈顶对象作为次栈顶对象StandardEngine.addLifecycleListener方法调用的参数,即设置到StandardEngine生命周期监听器数组中**/
digester.addSetNext(prefix + "Engine/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
注册生命周期监听器
addLifecycleListener()方法是从父类LifecycleBase继承.
public abstract class LifecycleBase implements Lifecycle {
/**
* 管理当前组件生命周期监听器列表
*/
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();
/**
* 给当前组件添加一个生命周期监听器
*/
@Override
public void addLifecycleListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
}
4.1.4 解析<Valve>标签
//解析<Server><Service><Engine><Valve>标签
/** 解析<Valve>标签实例化标签中className属性定义的对象,并push到操作栈中 **/
digester.addObjectCreate(prefix + "Engine/Valve",
null, // MUST be specified in the element
"className");
/** 解析<Valve>标签将标签中属性值映射到其实例化对象中**/
digester.addSetProperties(prefix + "Engine/Valve");
/** 解析<Valve>标签将操作栈栈顶对象作为次栈顶对象StandardEngine.addValve方法调用的参数,即设置到StandardEngine中Pipline组件中**/
digester.addSetNext(prefix + "Engine/Valve",
"addValve",
"org.apache.catalina.Valve");
给子pipeline组件添加Valve处理器
addValve()方法是从父类ContainerBase继承.
public abstract class ContainerBase extends LifecycleMBeanBase
implements Container {
/**
* 当前容器组件对应的pipeline组件
*/
protected final Pipeline pipeline = new StandardPipeline(this);
/**
* 给pipeline组件添加一个Valve
*/
public synchronized void addValve(Valve valve) {
pipeline.addValve(valve);
}
4.1.5 解析<Realm>标签
/** 解析<Realm>标签使用自定义规则组RealmRuleSet**/
digester.addRuleSet(new RealmRuleSet(prefix + "Engine/"));
/**
* 解析Realm标签添加到StandardEngine属性中
*/
@SuppressWarnings("deprecation")
public class RealmRuleSet extends RuleSetBase {
@Override
public void addRuleInstances(Digester digester) {
StringBuilder pattern = new StringBuilder(prefix);
for (int i = 0; i < MAX_NESTED_REALM_LEVELS; i++) {
if (i > 0) {
pattern.append('/');
}
pattern.append("Realm");
addRuleInstances(digester, pattern.toString(), i == 0 ? "setRealm" : "addRealm");
}
}
private void addRuleInstances(Digester digester, String pattern, String methodName) {
digester.addObjectCreate(pattern, null /* MUST be specified in the element */,
"className");
digester.addSetProperties(pattern);
digester.addSetNext(pattern, methodName, "org.apache.catalina.Realm");
digester.addRuleSet(new CredentialHandlerRuleSet(pattern + "/"));
}
}
4.2 EngineRuleSet规则组
@Override
public void addRuleInstances(Digester digester) {
//解析<Server><Service><Engine><Host>标签
/** 解析<Host>标签实例化StandardHost对象,并push到操作栈中 **/
digester.addObjectCreate(prefix + "Host",
"org.apache.catalina.core.StandardHost",
"className");
/** 解析<Host>标签将标签中属性值映射到其实例化对象中**/
digester.addSetProperties(prefix + "Host");
/** 解析<Host>标签,使用CopyParentClassLoaderRule规则,负责调用次栈顶对象getParentClassLoader获取父类加载,设置到栈顶对象parentClassLoader属性上 **/
digester.addRule(prefix + "Host",
new CopyParentClassLoaderRule());
/** 解析<Host>标签,使用LifecycleListenerRule规则,负责给栈顶对象添加一个生命周期监听器. 默认为hostConfigClass,或者在标签指定org.apache.catalina.startup.HostConfig属性**/
digester.addRule(prefix + "Host",
new LifecycleListenerRule
("org.apache.catalina.startup.HostConfig",
"hostConfigClass"));
/** 解析<Host>标签将操作栈栈顶对象作为次栈顶对象StandardService.addChild方法调用的参数,即将实例化StandardHost对象添加StandardServer.child子容器列表属性中**/
digester.addSetNext(prefix + "Host",
"addChild",
"org.apache.catalina.Container");
4.3 重要的规则
4.3.1 CopyParentClassLoaderRule规则
CopyParentClassLoaderRule规则,负责调用次栈顶对象getParentClassLoader获取父类加载,设置到栈顶对象parentClassLoader属性上
public class CopyParentClassLoaderRule extends Rule {
public CopyParentClassLoaderRule() {
}
@Override
public void begin(String namespace, String name, Attributes attributes)
throws Exception {
if (digester.getLogger().isDebugEnabled())
digester.getLogger().debug("Copying parent class loader");
Container child = (Container) digester.peek(0);
Object parent = digester.peek(1);
Method method =
parent.getClass().getMethod("getParentClassLoader", new Class[0]);
ClassLoader classLoader =
(ClassLoader) method.invoke(parent, new Object[0]);
child.setParentClassLoader(classLoader);
}
}
4.3.2 LifecycleListenerRule规则
LifecycleListenerRule 规则负责给栈顶对象添加一个生命周期监听器.
/**
* 解析标签给栈顶对象添加一个生命周期监听器
*/
public class LifecycleListenerRule extends Rule {
public LifecycleListenerRule(String listenerClass, String attributeName) {
this.listenerClass = listenerClass;
this.attributeName = attributeName;
}
/**
* 标准中指定属性,用来设置监听器处理类
*/
private final String attributeName;
/**
* 默认监听器处理类
*/
private final String listenerClass;
@Override
public void begin(String namespace, String name, Attributes attributes)
throws Exception {
/** 获取栈顶原始对象 **/
Container c = (Container) digester.peek();
/** 获取次栈顶元素对象 **/
Container p = null;
Object obj = digester.peek(1);
/** 如果栈顶元素对象是容器设置给p **/
if (obj instanceof Container) {
p = (Container) obj;
}
String className = null;
/** 获取标签attributeName值赋值给className **/
if (attributeName != null) {
String value = attributes.getValue(attributeName);
if (value != null)
className = value;
}
/** 获取次栈顶对象attributeName属性值赋值给className **/
if (p != null && className == null) {
String configClass =
(String) IntrospectionUtils.getProperty(p, attributeName);
if (configClass != null && configClass.length() > 0) {
className = configClass;
}
}
/** 如果className == null使用listenerClass作为className默认值**/
if (className == null) {
className = listenerClass;
}
/** 实例化className添加栈顶对象生命周期监听器列表中*/
Class<?> clazz = Class.forName(className);
LifecycleListener listener = (LifecycleListener) clazz.getConstructor().newInstance();
c.addLifecycleListener(listener);
}
}
组件生命周期
接下来初始化开始则进入tomcat组件的生命周期,对于tomcat中所有组件都必须实现Lifecycle,Tomcat 定义一个基类LifecycleBase 来实现 Lifecycle 接口,把一些公共的逻辑放到基类中实现,比如生命状态的转变与维护、生命事件的触发以及监听器的添加和删除等,而子类就负责实现自己的初始化、启动和停止等模板方法。为了避免跟基类中的方法同名,我们把具体子类的实现方法改个名字,在后面加上 Internal,叫 initInternal、startInternal 等。
StandardEngine父类对容器的初始化、启动和停止等模板方法进行的了默认实现。子类容器只需要重写父类实现即可实现扩展。
4.2 初始化StandardEngine
@Override
protected void initInternal() throws LifecycleException {
getRealm();
super.initInternal();
}
4.3 启动StandardEngine
@Override
protected synchronized void startInternal() throws LifecycleException {
if(log.isInfoEnabled()){
log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());
}
super.startInternal();
}
StandardEngine其他生命周期实现均从父类ContainerBase继承。
4.4 停止StandardEngine
/**
* 组件停止模板实现
*/
@Override
protected synchronized void stopInternal() throws LifecycleException {
/** 关闭处理定时任务线程 **/
threadStop();
/** 设置当前容器的状态LifecycleState.STOPPING **/
setState(LifecycleState.STOPPING);
/** 停止pipeline组件**/
if (pipeline instanceof Lifecycle &&
((Lifecycle) pipeline).getState().isAvailable()) {
((Lifecycle) pipeline).stop();
}
/** 使用线程池异步处理子容器关闭 **/
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (int i = 0; i < children.length; i++) {
results.add(startStopExecutor.submit(new StopChild(children[i])));
}
/** 等待所有子容器关闭完毕 **/
boolean fail = false;
for (Future<Void> result : results) {
try {
result.get();
} catch (Exception e) {
log.error(sm.getString("containerBase.threadedStopFailed"), e);
fail = true;
}
}
if (fail) {
throw new LifecycleException(
sm.getString("containerBase.threadedStopFailed"));
}
/** 关闭Realm组件**/
Realm realm = getRealmInternal();
if (realm instanceof Lifecycle) {
((Lifecycle) realm).stop();
}
/** 关闭Cluster组件**/
Cluster cluster = getClusterInternal();
if (cluster instanceof Lifecycle) {
((Lifecycle) cluster).stop();
}
}
4.5 销毁StandardEngine
/**
* 组件销毁模板实现
*/
@Override
protected void destroyInternal() throws LifecycleException {
/** 销毁Realm组件**/
Realm realm = getRealmInternal();
if (realm instanceof Lifecycle) {
((Lifecycle) realm).destroy();
}
/** 销毁cluster组件**/
Cluster cluster = getClusterInternal();
if (cluster instanceof Lifecycle) {
((Lifecycle) cluster).destroy();
}
/** 销毁cluster组件**/
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).destroy();
}
/** 清空所有子容器 **/
for (Container child : findChildren()) {
removeChild(child);
}
/** 父容器和当前容器组件取消关联 **/
if (parent != null) {
parent.removeChild(this);
}
/** 关闭处理子容器启动关闭线程池 **/
if (startStopExecutor != null) {
startStopExecutor.shutdownNow();
}
super.destroyInternal();
}
5 核心方法
5.1 重写addChild
@Override
public void addChild(Container child) {
if (!(child instanceof Host)){
throw new IllegalArgumentException
(sm.getString("standardEngine.notHost"));
}
super.addChild(child);
}
5.2 重写logAccess
/**
* AccessLog组件
*/
private final AtomicReference<AccessLog> defaultAccessLog =
new AtomicReference<>();
/**
* 使用AccessLog组件打印日志,
*
* 如果useDefault=true,使用defaultAccessLog属性中保存AccessLog打印日志
* 如果defaultAccessLog未初始化AccessLog,则尝试从子容器host,context获取绑定的AccessLog组件设置到defaultAccessLog,使用新设置AccessLog组件打印日志
*/
@Override
public void logAccess(Request request, Response response, long time,
boolean useDefault) {
boolean logged = false;
if (getAccessLog() != null) {
accessLog.log(request, response, time);
logged = true;
}
if (!logged && useDefault) {
AccessLog newDefaultAccessLog = defaultAccessLog.get();
/** 如果newDefaultAccessLog未初始化 **/
if (newDefaultAccessLog == null) {
/** 获取默认host子容器组件 **/
Host host = (Host) findChild(getDefaultHost());
Context context = null;
if (host != null && host.getState().isAvailable()) {
/** 获取host容器绑定的AccessLog 设置给 newDefaultAccessLog**/
newDefaultAccessLog = host.getAccessLog();
if (newDefaultAccessLog != null) {
if (defaultAccessLog.compareAndSet(null,
newDefaultAccessLog)) {
AccessLogListener l = new AccessLogListener(this,
host, null);
l.install();
}
} else {
/** 获取context容器绑定的AccessLog 设置给 newDefaultAccessLog**/
context = (Context) host.findChild("");
if (context != null &&
context.getState().isAvailable()) {
newDefaultAccessLog = context.getAccessLog();
if (newDefaultAccessLog != null) {
if (defaultAccessLog.compareAndSet(null,
newDefaultAccessLog)) {
/** 并设置AccessLogListener 作为当前容器对象engine,和子容器host的监听器。 **/
AccessLogListener l = new AccessLogListener(
this, null, context);
l.install();
}
}
}
}
}
/** 如果无法从子容器获取AccessLog,默认使用NoopAccessLog作为默认的AccessLog **/
if (newDefaultAccessLog == null) {
newDefaultAccessLog = new NoopAccessLog();
if (defaultAccessLog.compareAndSet(null,
newDefaultAccessLog)) {
/** 并设置AccessLogListener 作为当前容器对象engine,和子容器host的监听器。 **/
AccessLogListener l = new AccessLogListener(this, host,
context);
l.install();
}
}
}
/** 使用newDefaultAccessLog打印日志 **/
newDefaultAccessLog.log(request, response, time);
}
}
AccessLogListener
AccessLogListener同时实现3种监听器
protected static final class AccessLogListener
implements PropertyChangeListener, LifecycleListener,
ContainerListener {
绑定监听器,取消监听器
public void install() {
engine.addPropertyChangeListener(this);
if (host != null) {
host.addContainerListener(this);
host.addLifecycleListener(this);
}
if (context != null) {
context.addLifecycleListener(this);
}
}
private void uninstall() {
disabled = true;
if (context != null) {
context.removeLifecycleListener(this);
}
if (host != null) {
host.removeLifecycleListener(this);
host.removeContainerListener(this);
}
engine.removePropertyChangeListener(this);
}
监听事件处理
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (disabled) return;
String type = event.getType();
if (Lifecycle.AFTER_START_EVENT.equals(type) ||
Lifecycle.BEFORE_STOP_EVENT.equals(type) ||
Lifecycle.BEFORE_DESTROY_EVENT.equals(type)) {
engine.defaultAccessLog.set(null);
uninstall();
}
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (disabled) return;
if ("defaultHost".equals(evt.getPropertyName())) {
engine.defaultAccessLog.set(null);
uninstall();
}
}
@Override
public void containerEvent(ContainerEvent event) {
if (disabled) return;
if (Container.ADD_CHILD_EVENT.equals(event.getType())) {
Context context = (Context) event.getData();
if ("".equals(context.getPath())) {
engine.defaultAccessLog.set(null);
uninstall();
}
}
}
6 处理流程
每一个容器组件都有一个 Pipeline 对象,Pipeline 中维护了 Valve 链表,默认时每一个Pipeline存放了一个默认的BasicValue,
这里每一个Value表示一个处理点,当调用addValve 方法时会将添加Vaule添加到链表头部,Pipeline 中没有 invoke
方法,请求处理时Pipeline只需要获取链表中第一个Valve调用incoke去执行,执行完毕后当前Value会调用
getNext.invoke() 来触发下一个 Valve 调用
每一个容器在执行到最后一个默认BasicValue时,会负责调用下层容器的 Pipeline 里的第一个 Valve
Pipeline.jpg对于StandardEngine容器来说默认情况只添加了一个默认的StandardEngineValve。
7.1 StandardEngineValve
final class StandardEngineValve extends ValveBase {
public StandardEngineValve() {
super(true);
}
private static final StringManager sm =
StringManager.getManager(Constants.Package);
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
/** 获取host子容器组件 **/
Host host = request.getHost();
if (host == null) {
response.sendError
(HttpServletResponse.SC_BAD_REQUEST,
sm.getString("standardEngine.noHost",
request.getServerName()));
return;
}
/** 如果当前请求支持异步,则检查当前容器组件Pipeline管道种所有Value阀是否都支持异步,如果不是则重置为false **/
if (request.isAsyncSupported()) {
/** getPipeline().isAsyncSupported() 如果当前容器组件Pipeline管道种所有Value阀都支持异步则返回true**/
/** 设置当前请求是否支持异步,需要当前容器Pipeline管道种所有Value阀都支持异步 **/
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
}
/** 调用host容器的Pipeline管道的第一个Value阀执行 **/
host.getPipeline().getFirst().invoke(request, response);
}
}
7 EngineConfig监听器
解析xml种给StandardEngine组件添加LifecycleListener监听器,负责监听生命周期事件打印日志
public class EngineConfig
implements LifecycleListener {
private static final Log log = LogFactory.getLog(EngineConfig.class);
protected Engine engine = null;
protected static final StringManager sm =
StringManager.getManager(Constants.Package);
@Override
public void lifecycleEvent(LifecycleEvent event) {
try {
/** 获取触发事件的组件engine **/
engine = (Engine) event.getLifecycle();
} catch (ClassCastException e) {
log.error(sm.getString("engineConfig.cce", event.getLifecycle()), e);
return;
}
/** 如果当前事件START_EVENT,调用start()方法打印启动日志 **/
if (event.getType().equals(Lifecycle.START_EVENT))
start();
/** 如果当前事件STOP_EVENT,调用stop()方法打印停止日志 **/
else if (event.getType().equals(Lifecycle.STOP_EVENT))
stop();
}
protected void start() {
if (engine.getLogger().isDebugEnabled())
engine.getLogger().debug(sm.getString("engineConfig.start"));
}
protected void stop() {
if (engine.getLogger().isDebugEnabled())
engine.getLogger().debug(sm.getString("engineConfig.stop"));
}
}
网友评论