tomcat7.0运行过程解析
一、 接口和类概况
1. org.apache.catalina .Lifecycle接口:表示组件生命周期
(1) 签名:public interface Lifecycle
(2) 基本流程:NEW-->init(INITIALIZING-->INITIALIZED)
-->start(STARTING_PREP-->STARTING-->STARTED)
-->stop(STOPPING_PREP-->STOPPING-->STOPPED)
-->destroy(DESTROYING-->DESTROYED)
init分两个阶段, start,stop分三个阶段, destroy分两个阶段。
(2) 阶段之间的跳转关系图(参考Lifecycle接口中的图)
(3) 声明的方法:
public void addLifecycleListener(LifecycleListener listener)
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
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();
2. org.apache.catalina.util. LifecycleSupport类:为Lifecycle的实现提供支持,简化Lifecycle的实现
(1) 签名:public final class LifecycleSupport
(2) 构造函数:
public LifecycleSupport(Lifecycle lifecycle) {
super();
this.lifecycle = lifecycle;
}
(3) 已实现
public void addLifecycleListener(LifecycleListener listener)
public LifecycleListener[] findLifecycleListeners()
public void fireLifecycleEvent(String type, Object data)
public void removeLifecycleListener(LifecycleListener listener)
3. org.apache.catalina.util.LifecycleBase 类:实现了Lifecycle接口,完成大部分通用业务
(1) 签名:public abstract class LifecycleBase implements Lifecycle
(2) 重要成员:
private LifecycleSupport lifecycle = new LifecycleSupport(this); 利用它完成Lifecycle接口的实现
private volatile LifecycleState state = LifecycleState.NEW; 初始状态
(3) 定义抽象方法initInternal,startInternal,stopInternal,destroyInternal
(4) 实现了生命周期方法init,start,stop, destroy,并在实现内部分别调用对应的initInternal,startInternal,stopInternal,destroyInternal方法,以便子类可以增加个性化的业务逻辑
(5) 把生命周期方法执行的过程分阶段,并调用阶段设置方法setStateInternal设置相应阶段,在setStateInternal的内部调用fireLifecycleEvent(lifecycleEvent, data)来触发生命周期事件
4. org.apache.catalina.util.LifecycleMBeanBase 类:实现对Lifecycle对象的JMX管理
(1) 签名:public abstract class LifecycleMBeanBase extends LifecycleBase implements MBeanRegistration
(2) 主要是在initInternal中调用register(this, getObjectNameKeyProperties());
在destroyInternal中调用unregister(oname)。
5. org.apache.catalina.Container接口:表示容器组件
(1) 签名:public interface Container extends Lifecycle
(2) 重要的方法:
public Loader getLoader();
public void setLoader(Loader loader);
public Manager getManager();
public void setManager(Manager manager);
public Pipeline getPipeline();
public Container getParent();
public void setParent(Container container);
public ClassLoader getParentClassLoader();
public void setParentClassLoader(ClassLoader parent);
public void addChild(Container child);
public Container findChild(String name);
public Container[] findChildren();
public void invoke(Request request, Response response) throws IOException, ServletException;
public void removeChild(Container child);
public void backgroundProcess();
6. org.apache.catalina.core.ContainerBase类:实现容器的通用业务
(1) 签名:public abstract class ContainerBase extends LifecycleMBeanBase implements Container
(2) 重要的成员变量:
protected HashMap<String, Container> children = new HashMap<String, Container>();
protected Pipeline pipeline = new StandardPipeline(this);
protected ThreadPoolExecutor startStopExecutor;
(3) 当有连接请求的时候容器的调用
public void invoke(Request request, Response response) throws IOException, ServletException {
pipeline.getFirst().invoke(request, response);
}
(4) 初始化startStopExecutor(线程池执行器)
protected void initInternal() throws LifecycleException {
BlockingQueue<Runnable> startStopQueue =new LinkedBlockingQueue<Runnable>();
startStopExecutor = new ThreadPoolExecutor(getStartStopThreadsInternal(),
getStartStopThreadsInternal(), 10, TimeUnit.SECONDS,
startStopQueue,new StartStopThreadFactory(getName() + "-startStop-"));
startStopExecutor.allowCoreThreadTimeOut(true);
super.initInternal();
}
(5) 启动容器
protected synchronized void startInternal() throws LifecycleException {
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
logger = null;
getLogger();
if ((manager != null) && (manager instanceof Lifecycle))
((Lifecycle) manager).start();
if ((cluster != null) && (cluster instanceof Lifecycle))
((Lifecycle) cluster).start();
Realm realm = getRealmInternal();
if ((realm != null) && (realm instanceof Lifecycle))
((Lifecycle) realm).start();
if ((resources != null) && (resources instanceof Lifecycle))
((Lifecycle) resources).start();
// Start our child containers, if any
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<Future<Void>>();
for (int i = 0; i < children.length; i++) {
// StartChild是内部类,用来辅助启动子容器,签名如下:
// private static class StartChild implements Callable<Void>
//添加一个StartChild包装的Future到线程池startStopExecutor中运行
results.add(startStopExecutor.submit(new StartChild(children[i])));
}
boolean fail = false;
for (Future<Void> result : results) {
try {
result.get(); // 阻塞当前线程,等待子容器启动完成
} catch (Exception e) {
log.error(sm.getString("containerBase.threadedStartFailed"), e);
fail = true;
}
}
if (fail) {
throw new LifecycleException(
sm.getString("containerBase.threadedStartFailed"));
}
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
setState(LifecycleState.STARTING);
threadStart();
}
(6) stopInternal,destroyInternal方法类似startInternal
(7) 为管道增加阀门
public synchronized void addValve(Valve valve) {
pipeline.addValve(valve);
}
(8) 启动后台处理线程 通常只需Enegine容器启动
protected void threadStart() {
if (thread != null)
return;
if (backgroundProcessorDelay <= 0)
return;
threadDone = false;
String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
thread = new Thread(new ContainerBackgroundProcessor(), threadName);
thread.setDaemon(true);
thread.start();
}
(9) 内部类ContainerBackgroundProcessor:用于后台处理
public void run() {
while (!threadDone) {
try {
Thread.sleep(backgroundProcessorDelay * 1000L);
} catch (InterruptedException e) {}
if (!threadDone) {
Container parent = (Container) getMappingObject(); // parent为容器自身
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (parent.getLoader() != null) {
cl = parent.getLoader().getClassLoader();
}
processChildren(parent, cl);
}
}
}
protected void processChildren(Container container, ClassLoader cl) {
try {
if (container.getLoader() != null) {
Thread.currentThread().setContextClassLoader
(container.getLoader().getClassLoader());
}
container.backgroundProcess(); // 执行自身的后台处理
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error("Exception invoking periodic operation: ", t);
} finally {Thread.currentThread().setContextClassLoader(cl);}
Container[] children = container.findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i].getBackgroundProcessorDelay() <= 0) {
processChildren(children[i], cl); // 递归执行子容器的后台处理
}
}
}
(10) 后台业务处理
public void backgroundProcess() {
if (!getState().isAvailable())
return;
if (cluster != null) {
try {
cluster.backgroundProcess();
} catch (Exception e) {
log.warn(sm.getString("containerBase.backgroundProcess.cluster", cluster), e);
}
}
...... // 处理类似
}
(11) ContainerBase的四个子类
org.apache.catalina.core.StandardEngine :Selevet引擎 最外的容器,子容器为Host
org.apache.catalina.core.StandardHost:主机,子容器为Context
org.apache.catalina.core.StandardContext:上下文,即一个Web应用,子容器为Warpper
org.apache.catalina.core.StandardWarpper:包装器,最小的容器,不能再有子容器,包装一个Selevet
7. org.apache.catalina.Pipeline接口:把容器的执行流程划分成多个执行步骤,每个步骤由Value(阀门)执行,最后执行的为基本Value,一个管道与一个容器关联。
(1) 签名:public interface Pipeline
(2) 定义的方法:
public Valve getBasic();
public void setBasic(Valve valve);
public void addValve(Valve valve);
public Valve[] getValves();
public void removeValve(Valve valve);
public Valve getFirst();
public Container getContainer();
public void setContainer(Container container);
public boolean isAsyncSupported();
8. org.apache.catalina.core.StandardPipeline类:Pipeline的标准实现
(1) 签名:public class StandardPipeline extends LifecycleBase implements Pipeline, Contained
9. org.apache.catalina.Valve接口:表示Pipeline中的一个执行步骤
(1) 签名:public interface Valve
(2) 声明的方法:
public Valve getNext();
public void setNext(Valve valve);
public void backgroundProcess();
public void invoke(Request request, Response response)throws IOException, ServletException;
public void event(Request request, Response response, CometEvent event)throws IOException, ServletException;
public boolean isAsyncSupported();
10. org.apache.catalina.valves.ValveBase类:Valve的基本实现
(1) 签名:public abstract class ValveBase extends LifecycleMBeanBase implements Contained, Valve
(2) ValveBase的四个子类:
org.apache.catalina.core.StandardEngineValve 引擎容器的基本阀门
org.apache.catalina.core.StandardHostValve主机容器的基本阀门
org.apache.catalina.core.StandardContextValve上下文引擎容器的基本阀门
org.apache.catalina.core.StandardWrapperValve包装器容器的基本阀门
(基本阀门在最后调用,它会根据请求路由到相应的子容器并触发子容器管道的第一个阀门的invoke方法,对于Wrapper容器来说它没有子容器,而是触发ApplicationFilterChain的doFilter方法,doFilter里面调用internalDoFilter方法,internalDoFilter里面调用Filter的doFilter,最后调用Servlet的service)
11. 其他重要的接口和类:
(1) org.apache.catalina.startup.Bootstrap类:启动引导
(2) org.apache.catalina.startup. Catalina类:包装Server
(3) org.apache.catalina.Server接口和org.apache.catalina.core.StandardServer类:表示服务器,可以包含一个或多个服务
(4) org.apache.catalina.Service接口和org.apache.catalina.core.StandardService类:表示一个服务,可以包含一个或多个连接器,以及一个引擎。
(5) org.apache.catalina.connector.Connector类: 表示一个连接器。
(6) org.apache.catalina.Engine接口和org.apache.catalina.core.StandardEngine类:表示一个引擎,可以包含一个或多个虚拟主机
(7) org.apache.catalina.Host接口和org.apache.catalina.core.StandardHost类:表示一个虚拟主机,可以包含一个或多个Web应用
(8) org.apache.catalina.Context接口和org.apache.catalina.core.StandardContext类:表示一个Web应用,可以有许多个包装器
(9) org.apache.catalina.Wrapper接口和org.apache.catalina.core.StandardWrapper类:表示一个Servlet包装器,用来管理一个Servlet的加载,初始化,调用等(调用是间接由包装器的基本阀门完成的)。
二、 类之间的调用过程概况
1. org.apache.catalina.startup.Bootstrap.main 启动类概况
public static void main(String args[]) {
if (daemon == null) {
// Don't set daemon until init() has completed
Bootstrap bootstrap = new Bootstrap(); //创建启动类
try {
bootstrap.init(); //初始化Catalina
} catch (Throwable t) {
handleThrowable(t);
t.printStackTrace();
return;
}
daemon = bootstrap; //保存Bootstrap
}
try {
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
}
} else if (command.equals("start")) {
daemon.setAwait(true); //设置Catalina等待状态
daemon.load(args); //加载Catalina
daemon.start(); //启动Catalina
}
}
}
2. bootstrap.init
public void init() throws Exception
{
// 设置Catalina路径
setCatalinaHome();
setCatalinaBase();
//创建StandardClassLoader类加载器
initClassLoaders();
// 设置StandardClassLoader类加载器为线程上下文加载器
Thread.currentThread().setContextClassLoader(catalinaLoader);
SecurityClassLoad.securityClassLoad(catalinaLoader);
if (log.isDebugEnabled())
log.debug("Loading startup class");
Class<?> startupClass =
catalinaLoader.loadClass
("org.apache.catalina.startup.Catalina");
//创建Catalina实例
Object startupInstance = startupClass.newInstance();
if (log.isDebugEnabled())
log.debug("Setting startup class properties");
//设置Catalina的ParentClassLoader
String methodName = "setParentClassLoader";
Class<?> paramTypes[] = new Class[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object paramValues[] = new Object[1];
paramValues[0] = sharedLoader;
Method method =
startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);
//把Catalina对象设置到Bootstrap对象中
catalinaDaemon = startupInstance;
}
3. bootstrap. setAwait 调用Catalina的setAwait方法,设置Catalina的await=true;
4. bootstrap. load 执行过程如下:
bootstrap.load() >>
Catalina.load(String args[])
Catalina.load()>>
Digester digester = createStartDigester()
digester.parse(inputSource) //根据server.xml创建StandardServer对象
getServer().init()>>
Server.initInternal()>>
services[i].init()>>
Service.initInternal()>>
container.init()
connector.init()>>
connector.initInternal>>
adapter = new CoyoteAdapter(this) //创建CoyoteAdapter并向其设置Connector
protocolHandler.setAdapter(adapter) //往Http11Protocol中设置CoyoteAdapter
protocolHandler.init()>>
endpoint.init()>>
endpoint.bind()>>
serverSocket = serverSocketFactory.createSocket(getPort(),getBacklog())
5. bootstrap. start 执行过程如下:
bootstrap.start () >>
Catalina.start ()>>
getServer().start()>>Server.startInternal>>
services[i].start()>>Service.tartInternal>>
container.start()>>container.startInternal()
connector.start()>>
protocolHandler.start()>>
endpoint.start()>>endpoint .startInternal()>>
createExecutor() //创建请求处理线程池
startAcceptorThreads() //创建并启动请求接收线程
mapperListener.start()>>mapperListener.startInternal>>
registerHost(host)>>
registerContext((Context)container)>>
registerWrapper((Wrapper)container)>>
mapper.addWrapper(..) //添加JSP或Servlet包装器
注意:Catalina.start完成之后调用await()方法,进而调用getServer().await(),然后线程就停留在StandardServer的await中,通过ServerSocket监听对服务器的停机命令,如果没有停机命令,则一直等待下去
6. startAcceptorThreads启动之后,就可以接收请求了
org.apache.tomcat.util.net. JIoEndpoint.Acceptor. run()>> //请求接收线程
socket = serverSocketFactory.acceptSocket(serverSocket)
processSocket(socket)>>
getExecutor().execute(new SocketProcessor(wrapper))>>
JIoEndpoint.SocketProcessor.run()>> //请求处理线程
handler.process(socket,status)>>
Http11Processor.process(socket)>>
CoyoteAdapter.service(request, response)>>
connector.getContainer().getPipeline().getFirst().invoke(request, response)>>
host.getPipeline().getFirst().invoke(request, response)>>
context.getPipeline().getFirst().invoke(request, response)>>
wrapper.getPipeline().getFirst().invoke(request, response)>>
filterChain.doFilter(request,response)>>
internalDoFilter(request, response)>>
servlet.service(request, response)
7. Catalina运行过程中的线程概况
(1) main主线程:即从main开始执行的线程,在启动Catalina之后就一直在Server的await方法中等待关闭命令,如果未接收到关闭命令就一直等待下去。main线程一直运行着。
启动过程:Bootstrap.main>>Catalina.start>>Catalina.await()>>Server.await()
(2) 子容器启动与关闭线程:ContainerBase的protected ThreadPoolExecutor startStopExecutor 容器线程池执行器[处理子容器的启动和停止]在ContainerBase. initInternal()方法中进行初始化
作用:在ContainerBase. startInternal()方法中启动子容器,在ContainerBase. stopInternal ()方法中停止子容器,
即处理子容器的启动和停止事件。
子容器线程池创建过程:StandardService.initInternal>>ContainerBase.initInternal>>new ThreadPoolExecutor()
启动过程:StandardService.startInternal>>ContainerBase.startInternal>>startStopExecutor.submit(new StartChild(Child)或StopChild(Child))>>execute(ftask)>>addIfUnderCorePoolSize(command)
addIfUnderCorePoolSize内容如下:
private boolean addIfUnderCorePoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (poolSize < corePoolSize && runState == RUNNING)
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
if (t == null)
return false;
t.start(); // StartChild.call()被调用,调用子容器的child.start()启动子容器
return true;
}
private Thread addThread(Runnable firstTask) {
Worker w = new Worker(firstTask);
// threadFactory为ContainerBase内部类StartStopThreadFactory
Thread t = threadFactory.newThread(w);
if (t != null) {
w.thread = t;
workers.add(w);
int nt = ++poolSize;
if (nt > largestPoolSize)
largestPoolSize = nt;
}
return t;
}
(3) 容器的后台处理线程ContainerBackgroundProcessor:
启动过程:StandardService.startInternal>>ContainerBase.startInternal >> ContainerBase.threadStart()
ContainerBase.startInternal(){
for(int i=0 ;i < children.length;i++){
startStopExecutor.submit(new StartChild(children[i]); //起新线程启动子容器
}
threadStart();// 在启动容器的最后调用threadStart方法
}
protected void threadStart() {
if (thread != null)
return;
// backgroundProcessorDelay默认为-1,即不产生后台线程,但StandardEngine的构造
// 函数中设置backgroundProcessorDelay = 10,即默认只有Engine产生后台线程,
// 其它子容器共享Engine的后台线程
if (backgroundProcessorDelay <= 0)
return;
threadDone = false;
String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
thread = new Thread(new ContainerBackgroundProcessor(), threadName);
thread.setDaemon(true);
thread.start(); // 启动容器后台线程
}
ContainerBackgroundProcessor是一个内部类,处理方式参考前面ContainerBase小节的内部类处理。
(4) 请求接收线程,即运行Acceptor的线程,启动Connector的时候产生
启动过程:StandardService.startInternal>>Connector.startInternal()>>protocolHandler.start()>>AbstractProtocol.start()>>endpoint.start()>>AbstractEndpoint.Start()>>JioEndpoint.startInternal()>>JIoEndpoint.startAcceptorThreads()
startAcceptorThreads内容如下:
protected final void startAcceptorThreads() {
int count = getAcceptorThreadCount(); // 默认只有一个接收线程Acceptor
acceptors = new Acceptor[count];
for (int i = 0; i < count; i++) {
acceptors[i] = createAcceptor(); // org.apache.tomcat.util.net. JIoEndpoint.Acceptor
Thread t = new Thread(acceptors[i], getName() + "-Acceptor-" + i); //创建请求接收线程
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start(); // 启动接收线程来接收请求
}
}
这样在Acceptor的run()中就可以接收请求了。
(5) 请求处理线程,即运行SocketProcessor的线程,从请求处理线程池中产生
org.apache.tomcat.util.net. AbstractEndpoint的成员变量private Executor executor用来处理请求;
org.apache.tomcat.util.net. JioEndpoint(继承了AbstractEndpoint)在方法startInternal()中调用createExecutor()
来创建executor为线程池对象ThreadPoolExecutor
请求处理线程池创建过程:StandardService.startInternal>>Connector.startInternal>>protocolHandler.start>>AbstractProtocol.start>>endpoint.start>>AbstractEndpoint.Start>>JIoEndpoint.startInternal>>JIoEndpoint.createExecutor>>new ThreadPoolExecutor()
public void createExecutor() {
internalExecutor = true;
TaskQueue taskqueue = new TaskQueue();
// 线程池线程产生的的工厂为java.util.concurrent.ThreadFactory.TaskThreadFactory
TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
taskqueue.setParent( (ThreadPoolExecutor) executor);
}
启动过程:Acceptor.run()>> // 请求接收线程接收到请求后
processSocket(socket)>>
getExecutor().execute(new SocketProcessor(wrapper))>> // 交给请求处理线程处理
ThreadPoolExecutor.execute (command,0,TimeUnit.MILLISECONDS)>>
super.execute(command)>>
addIfUnderCorePoolSize(command)
addIfUnderCorePoolSize内容如下:
private boolean addIfUnderCorePoolSize(Runnable firstTask) {
Thread t = null;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (poolSize < corePoolSize && runState == RUNNING)
t = addThread(firstTask);
} finally {
mainLock.unlock();
}
if (t == null)
return false;
t.start(); // SocketProcessor.run运行
return true;
}
private Thread addThread(Runnable firstTask) {
Worker w = new Worker(firstTask);
// threadFactory为TaskThreadFactory
Thread t = threadFactory.newThread(w);
if (t != null) {
w.thread = t;
workers.add(w);
int nt = ++poolSize;
if (nt > largestPoolSize)
largestPoolSize = nt;
}
return t;
}
至此SocketProcessor.run运行起来了,这个线程负责处理请求。
三、 处理过程详细讲解
处理的过程主要分为加载、启动、请求处理、关闭四个过程。
1. 加载过程
(1) 第一层
// Catalina加载的全过程都在该方法中完成
org.apache.catalina.startup.Catalina.load(){
long t1 = System.nanoTime();
initDirs();
initNaming();
Digester digester = createStartDigester(); // 构建Digester
InputSource inputSource = null;
InputStream inputStream = null;
File file = null;
try {
file = configFile(); // 获取server.xml文件,以便转换成流
inputStream = new FileInputStream(file);
inputSource = new InputSource(file.toURI().toURL().toString());
}
……
try {
inputSource.setByteStream(inputStream);
digester.push(this); // 把digester自己压入栈底
digester.parse(inputSource); // 根据server.xml创建StandardServer对象
}
getServer().setCatalina(this); // 设置关联
initStreams();
try {
getServer().init(); // 初始化StandardServer
}
long t2 = System.nanoTime();
if(log.isInfoEnabled()) {
log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms"); // 计算初始化时间
}
}
// 整个方法就是添加一个针对Server.xml的解析规则集,当执行digester.parse方法的时候,
// 根据该规则集生成对象以及对象之间的关系,具体就不介绍了
org.apache.catalina.startup.Catalina.Digester createStartDigester() {
Digester digester = new Digester();
……
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.NamingResources");
digester.addSetProperties("Server/GlobalNamingResources");
digester.addSetNext("Server/GlobalNamingResources",
"setGlobalNamingResources",
"org.apache.catalina.deploy.NamingResources");
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");
……
// 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/"));
……
return (digester); // 返回digester
}
// 规则集HostRuleSet的方法addRuleInstances为WebApp的加载提供了可能
// 当digester解析到Host元素开始标记的时候执行LifecycleListenerRule.begin方法
org.apache.catalina.startup.HostRuleSet.addRuleInstances (Digester digester) {
……
digester.addRule(prefix + "Host",
new LifecycleListenerRule // 添加一个LifecycleListenerRule规则
("org.apache.catalina.startup.HostConfig", // 默认类HostConfig
"hostConfigClass")); // XML节点属性名,如果有则其值代替默认类
……
}
// digester解析到XML节点开始标记的时候调用(此处是节点Host)
org.apache.catalina.startup.LifecycleListenerRule.begin(String namespace, String name, Attributes attributes){
Container c = (Container) digester.peek(); // c为StandardHost
……
Class<?> clazz = Class.forName(className); // className默认为org.apache.catalina.startup.HostConfig
LifecycleListener listener = (LifecycleListener) clazz.newInstance();
c.addLifecycleListener(listener); // 给StandardHost添加事件监听器
}
(2) 第二层
// 初始化服务器,方法init是基类LifecycleBase实现的,catalina里面的组件基本都继承了它
// 所以以后讲组件的init直接跳到initInternal,用(init>)initInternal()表示
org.apache.catalina.core.StandardServer[Lifecycle].init(){
……
// 设置容器状态为LifecycleState. INITIALIZING,并触发生命周期事件
setStateInternal(LifecycleState.INITIALIZING, null, false);
try {
initInternal(); // 一般子类重写initInternal,添加个性化业务
}
……
// 设置容器状态为LifecycleState. INITIALIZED,并触发生命周期事件
setStateInternal(LifecycleState.INITIALIZED, null, false);
}
org.apache.catalina.core.StandardServer. initInternal(){
super.initInternal(); // JMX管理有关
……
for (int i = 0; i < services.length; i++) {
services[i].init(); // 初始化服务
}
}
(3) 第三层
// 初始化服务
org.apache.catalina.core. StandardService.(init>) initInternal{
super.initInternal();
if (container != null) { container.init();} // 初始化StandardEngine容器
for (Executor executor : findExecutors()) {
……
executor.init();
}
synchronized (connectors) {
for (Connector connector : connectors) {
try { connector.init();} // 连接器初始化,通常有两个
……
}
}
}
(4) 第四层
// 初始化StandardEngine
org.apache.catalina.core.StandardEngine.(init>)initInternal(){
getRealm();
super.initInternal(); // ContainerBase.initInternal
}
org.apache.catalina.core. ContainerBase.initInternal(){
BlockingQueue<Runnable> startStopQueue =
new LinkedBlockingQueue<Runnable>();
startStopExecutor = new ThreadPoolExecutor( // 初始化子容器启动关闭线程池
getStartStopThreadsInternal(),
getStartStopThreadsInternal(), 10, TimeUnit.SECONDS,
startStopQueue,
new StartStopThreadFactory(getName() + "-startStop-"));
startStopExecutor.allowCoreThreadTimeOut(true);
super.initInternal();
}
// 初始化连接器Connector,通常启动的时候连接器有两个,查看Server.xml可以看到配置了两个连接器节点
// 其中一个是为HTTP/1.1协议服务的,另一个是为AJP/1.3协议,这里以HTTP/1.1讲解
org.apache.catalina.connector.Connector.(init>)initInternal(){
super.initInternal();
adapter = new CoyoteAdapter(this); // 创建CoyoteAdapter对象并向其设置Connector
protocolHandler.setAdapter(adapter); // 向Http11Protocol设置CoyoteAdapter
…….
try {
protocolHandler.init(); // 初始化Http11Protocol
} catch (Exception e) {
throw new LifecycleException
(sm.getString
("coyoteConnector.protocolHandlerInitializationFailed"), e);
}
// org.apache.catalina.connector.MapperListener,Mapper监听器
// Mapper:servlet API mapping rules(源代码解释)
// 即Mapper能够对当前请求路由到相应的主机,Web应用,包装器
mapperListener.init();
}
(5) 第四层
org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(){
sslImplementation = SSLImplementation.getInstance(sslImplementationName);
super.init(); // org.apache.coyote.AbstractProtocol
}
org.apache.coyote.AbstractProtocol.init(){
……
endpoint.init(); //初始化JIoEndpoint
……
}
(6) 第五层
org.apache.tomcat.util.net.JIoEndpoint[AbstractEndpoint].init(){
bind();
}
org.apache.tomcat.util.net.JIoEndpoint.bind(){
if (acceptorThreadCount == 0) {
// 请求接收线程数,默认为1
acceptorThreadCount = 1;
}
if (getMaxConnections() == 0) {
// User hasn't set a value - use the default
setMaxConnections(getMaxThreadsExecutor(true));
}
if (serverSocketFactory == null) {
if (isSSLEnabled()) {
serverSocketFactory =
handler.getSslImplementation().getServerSocketFactory(this);
} else {
serverSocketFactory = new DefaultServerSocketFactory(this);
}
}
if (serverSocket == null) {
try {
if (getAddress() == null) {
// 创建一个用于监听指定端口请求的serverSocket, 默认8080端口
serverSocket = serverSocketFactory.createSocket(getPort(),
getBacklog());
} else {
serverSocket = serverSocketFactory.createSocket(getPort(),
getBacklog(), getAddress());
}
}
}
}
2. 启动过程
(1) 第一层
Catalina启动过程便是服务器的启动过程,Catalina的start方法结束则服务器也就停止了,但通常它一直会驻留在服务器的await方法中等待关闭命令。
org.apache.catalina.startup.Catalina. start(){
……
long t1 = System.nanoTime();
try {
getServer().start(); // 启动StandardServer
} catch (LifecycleException e) {
log.error("Catalina.start: ", e);
}
long t2 = System.nanoTime();
if(log.isInfoEnabled()) {
log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms"); // 计算启动时间
}
if (useShutdownHook) {
if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);
……
}
if (await) {
await(); // 调用服务器等待方法,监听Socket关机请求
stop(); // 停止服务器
}
}
(2) 第二层
// 启动服务器,方法start是基类Lifecycle实现的,catalina里面的组件基本都继承了它,
// 所以以后讲组件的start直接跳到startInternal,用cmpt.( start>)startInternal()表示
org.apache.catalina.core.StandardServer[LifecycleBase].start(){
……
if (state.equals(LifecycleState.NEW)) {
init(); // 如果组件状态是NEW,还没初始化,则先进行初始化
} else if (state.equals(LifecycleState.FAILED)){
stop(); // 如果状态是FAILED,停止服务器
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}
setStateInternal(LifecycleState.STARTING_PREP, null, false); // 设置启动前状态并触发事件
try {
startInternal(); // 调用StandardServer的startInternal方法
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.startFail",toString()), 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); // 设置启动完成状态并触发事件
}
}
org.apache.catalina.core.StandardServer. startInternal(){
fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING); // 设置启动中状态并触发事件
globalNamingResources.start();
// Start our defined Services
synchronized (services) {
for (int i = 0; i < services.length; i++) {
services[i].start(); // 启动服务
}
}
}
(3) 第三层
// 启动连接器,默认连接器有连个,这里以协议HTTP1.1讲解
org.apache.catalina.core. StandardService.( start>)startInternal(){
if(log.isInfoEnabled())
log.info(sm.getString("standardService.start.name", this.name));
setState(LifecycleState.STARTING); // 设置启动中状态并触发事件
if (container != null) {
synchronized (container) {
container.start(); // 启动容器StandardEngine,并且会启动所有子容器
}
}
synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}
synchronized (connectors) {
for (Connector connector: connectors) {
try {
// If it has already failed, don't try and start it
if (connector.getState() != LifecycleState.FAILED) {
connector.start(); // 启动连接器Connector
}
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connector), e);
}
}
}
}
(4) 第四层
// 启动StandardEnine
org.apache.catalina.core. StandardEngine.( start>)startInternal(){
// Log our server identification information
if(log.isInfoEnabled())
log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());
// Standard container startup
super.startInternal();
}
org.apache.catalina.core.ContainerBase.startInternal(){
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start(); // 启动加载器
logger = null;
getLogger();
if ((manager != null) && (manager instanceof Lifecycle))
((Lifecycle) manager).start(); // 启动管理器
if ((cluster != null) && (cluster instanceof Lifecycle))
((Lifecycle) cluster).start();
Realm realm = getRealmInternal();
if ((realm != null) && (realm instanceof Lifecycle))
((Lifecycle) realm).start();
if ((resources != null) && (resources instanceof Lifecycle))
((Lifecycle) resources).start();
// Start our child containers, if any
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<Future<Void>>();
for (int i = 0; i < children.length; i++) {
// 在线程池中启动子容器,请参考前面的线程小节“容器线程池”调用StartChild. Call()
results.add(startStopExecutor.submit(new StartChild(children[i])));
}
boolean fail = false;
for (Future<Void> result : results) {
try {
result.get(); // 阻塞当前线程,等待子容器启动完成
} catch (Exception e) {
log.error(sm.getString("containerBase.threadedStartFailed"), e);
fail = true;
}
}
if (fail) {
throw new LifecycleException(
sm.getString("containerBase.threadedStartFailed"));
}
// Start the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start(); // 启动容器管道
setState(LifecycleState.STARTING); // 设置启动中状态并触发事件
threadStart(); // 启动引擎容器后台线程,请参考前面的线程小节“容器的后台处理线程”
}
// 启动连接器
org.apache.catalina.connector.Connector.( start>)startInternal(){
if (getPort() < 0) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort", Integer.valueOf(getPort())));
}
setState(LifecycleState.STARTING); // 设置启动中状态并触发事件
try {
protocolHandler.start(); // 启动特定协议处理器Http11Protocol
} catch (Exception e) {
String errPrefix = "";
if(this.service != null) {
errPrefix += "service.getName(): \"" + this.service.getName() + "\"; ";
}
throw new LifecycleException
(errPrefix + " " + sm.getString
("coyoteConnector.protocolHandlerStartFailed"), e);
}
mapperListener.start(); // 启动Mapper监听器
}
(5) 第五层
// child为StandardEngine的子容器StandardHost
org.apache.catalina.core.ContainerBase.StartChild.call (){
child.start();
return null;
}
// 启动主机,注意在启动主机的事件LifecycleState.STARTING中,将执行监听器部署WebApp
// 这个事件监听器如何添加的,请参考前面小节“加载过程”的“第一层”
org.apache.catalina.core. StandardHost.( start>)startInternal(){
String errorValve = getErrorReportValveClass();
if ((errorValve != null) && (!errorValve.equals(""))) {
try {
boolean found = false;
Valve[] valves = getPipeline().getValves();
for (Valve valve : valves) {
if (errorValve.equals(valve.getClass().getName())) {
found = true; // 找到错误报告阀门
break;
}
}
if(!found) {
Valve valve =
(Valve) Class.forName(errorValve).newInstance();
getPipeline().addValve(valve); // 没有找到错误报告阀门,则添加
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString(
"standardHost.invalidErrorReportValveClass",
errorValve), t);
}
}
// 调用基类ContainerBase的startInternal,将触发Host组件的STARTING事件
super.startInternal();
}
// 主机Host的STARTING事件监听器HostConfig来处理STARTING事件
org.apache.catalina.startup.HostConfig.lifecycleEvent(LifecycleEvent event) {
if (event.getType().equals(Lifecycle.PERIODIC_EVENT))
check();
try {
host = (Host) event.getLifecycle();
if (host instanceof StandardHost) {
setCopyXML(((StandardHost) host).isCopyXML());
setDeployXML(((StandardHost) host).isDeployXML());
setUnpackWARs(((StandardHost) host).isUnpackWARs());
}
} catch (ClassCastException e) {
log.error(sm.getString("hostConfig.cce", event.getLifecycle()), e);
return;
}
// Process the event that has occurred
if (event.getType().equals(Lifecycle.START_EVENT))
start(); // 处理Host组件的STARTING事件
else if (event.getType().equals(Lifecycle.STOP_EVENT))
stop();
}
org.apache.catalina.startup.HostConfig.start (){
……
if (host.getDeployOnStartup())
deployApps(); // 部署WebApp应用
}
// 部署WebApp 分三种
org.apache.catalina.startup.HostConfig. deployApps (){
File appBase = appBase();
File configBase = configBase();
String[] filteredAppPaths = filterAppPaths(appBase.list());
// Deploy XML descriptors from configBase
deployDescriptors(configBase, configBase.list()); // 根据部署描述符部署
// Deploy WARs
deployWARs(appBase, filteredAppPaths); // 部署WAR文件的WebApp
// Deploy expanded folders
deployDirectories(appBase, filteredAppPaths);} // 部署目录形式的WebApp
}
(6) 第六层:部署WebApp(以deployDirectories讲解)
// appBase 是webapps,即WebApp根目录
// files即将部署的WebApp目录集,如examples
org.apache.catalina.startup.HostConfig.deployDirectories(File appBase, String[] files){
if (files == null)
return;
ExecutorService es = host.getStartStopExecutor();
List<Future<?>> results = new ArrayList<Future<?>>();
for (int i = 0; i < files.length; i++) {
if (files[i].equalsIgnoreCase("META-INF"))
continue;
if (files[i].equalsIgnoreCase("WEB-INF"))
continue; // 跳过特殊目录
File dir = new File(appBase, files[i]);
if (dir.isDirectory()) {
// ContextName为WebApp名称,即WebApp目录名 如:“/examples”
ContextName cn = new ContextName(files[i]);
if (isServiced(cn.getName()) || deploymentExists(cn.getName()))
continue;
results.add(es.submit(new DeployDirectory(this, cn, dir))); // 线程池执行部署WebApp
}
}
for (Future<?> result : results) {
try {
result.get(); // 阻塞当前线程,等待所有WebApp部署完成
} catch (Exception e) {
log.error(sm.getString(
"hostConfig.deployDir.threaded.error"), e);
}
}
}
org.apache.catalina.startup.HostConfig.DeployDirectory.run{
config.deployDirectory(cn, dir);
}
org.apache.catalina.startup.HostConfig.deployDirectory(ContextName cn, File dir){
DeployedApplication deployedApp = new DeployedApplication(cn.getName()); // 创建一个部署应用
if( log.isInfoEnabled() )
log.info(sm.getString("hostConfig.deployDir",dir.getAbsolutePath()));
Context context = null;
File xml = new File(dir, Constants.ApplicationContextXml);
File xmlCopy = null;
try {
if (deployXML && xml.exists()) {
synchronized (digester) {
try {
context = (Context) digester.parse(xml);
} catch (Exception e) {
log.error(sm.getString(
"hostConfig.deployDescriptor.error",
xml));
context = new FailedContext();
} finally {
digester.reset();
}
}
if (copyXML) {
xmlCopy = new File(configBase(), cn.getBaseName() + ".xml");
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(xml);
os = new FileOutputStream(xmlCopy);
IOTools.flow(is, os);
// Don't catch IOE - let the outer try/catch handle it
} finally {
try {
if (is != null) is.close();
} catch (IOException e){
// Ignore
}
try {
if (os != null) os.close();
} catch (IOException e){
// Ignore
}
}
context.setConfigFile(xmlCopy.toURI().toURL());
} else {
context.setConfigFile(xml.toURI().toURL());
}
} else {
context = (Context) Class.forName(contextClass).newInstance(); // 默认为StandardContext
}
// 添加StandardContext组件的事件监听器org.apache.catalina.startup.ContextConfig
Class<?> clazz = Class.forName(host.getConfigClass());
LifecycleListener listener = (LifecycleListener) clazz.newInstance();
context.addLifecycleListener(listener);
context.setName(cn.getName());
context.setPath(cn.getPath());
context.setWebappVersion(cn.getVersion());
context.setDocBase(cn.getBaseName());
host.addChild(context); // 添加到Host,并启动子容器Context
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("hostConfig.deployDir.error",
dir.getAbsolutePath()), t);
} finally {
deployedApp.redeployResources.put(dir.getAbsolutePath(),
Long.valueOf(dir.lastModified()));
if (deployXML && xml.exists()) {
if (xmlCopy == null) {
deployedApp.redeployResources.put(
xml.getAbsolutePath(),
Long.valueOf(xml.lastModified()));
} else {
deployedApp.redeployResources.put(
xmlCopy.getAbsolutePath(),
Long.valueOf(xmlCopy.lastModified()));
}
}
addWatchedResources(deployedApp, dir.getAbsolutePath(), context);
addGlobalRedeployResources(deployedApp);
}
deployed.put(cn.getName(), deployedApp); // 添加到已经部署应用deployed中
}
org.apache.catalina.core.StandardHost.addChild(Container child){
child.addLifecycleListener(new MemoryLeakTrackingListener());
if (!(child instanceof Context))
throw new IllegalArgumentException
(sm.getString("standardHost.notContext"));
super.addChild(child); // ContainerBase.addChild
}
org.apache.catalina.core.ContainerBase.addChild(Container child){
if (Globals.IS_SECURITY_ENABLED) {
PrivilegedAction<Void> dp =
new PrivilegedAddChild(child);
AccessController.doPrivileged(dp);
} else {
addChildInternal(child); // ContainerBase.addChildInternal
}
org.apache.catalina.core.ContainerBase.addChildInternal(Container child){
if( log.isDebugEnabled() ) log.debug("Add child " + child + " " + this);
synchronized(children) {
if (children.get(child.getName()) != null)
throw new IllegalArgumentException("addChild: Child name '" +
child.getName() +"' is not unique");
child.setParent(this); // May throw IAE
children.put(child.getName(), child); // 添加子容器StandardContext
}
if ((getState().isAvailable() ||
LifecycleState.STARTING_PREP.equals(getState())) &&
startChildren) {
try {
child.start(); // 启动子容器StandardContext
} catch (LifecycleException e) {
log.error("ContainerBase.addChild: start: ", e);
throw new IllegalStateException
("ContainerBase.addChild: start: " + e);
}
}
fireContainerEvent(ADD_CHILD_EVENT, child);
}
org.apache.catalina.core.StandardContext.(start>)startInternal(){
if(log.isDebugEnabled()) log.debug("Starting " + getBaseName());
if (this.getObjectName() != null) {
Notification notification = new Notification("j2ee.state.starting",
this.getObjectName(), sequenceNumber.getAndIncrement());
broadcaster.sendNotification(notification);
}
setConfigured(false);
boolean ok = true;
if (namingResources != null) {
namingResources.start();
}
// Add missing components as necessary
if (webappResources == null) { // (1) Required by Loader
if (log.isDebugEnabled())
log.debug("Configuring default Resources");
try {
if ((getDocBase() != null) && (getDocBase().endsWith(".war")) &&
(!(new File(getBasePath())).isDirectory()))
setResources(new WARDirContext());
else
setResources(new FileDirContext());
} catch (IllegalArgumentException e) {
log.error("Error initializing resources: " + e.getMessage());
ok = false;
}
}
if (ok) {
if (!resourcesStart()) {
log.error( "Error in resourceStart()");
ok = false;
}
}
if (getLoader() == null) {
WebappLoader webappLoader = new WebappLoader(getParentClassLoader()); // 类加载器
webappLoader.setDelegate(getDelegate());
setLoader(webappLoader); //启动WebAppLoader载入器,创建WebAppClassLoader类加载器
}
getCharsetMapper();
postWorkDirectory();
………
try {
if (ok) {
…….
// 触发CONFIGURE_START_EVENT事件
// 通知ContextConfig监听器ContextConfig.lifecycleEvent(LifecycleEvent event)
// 根据web.xml配置StandardContext
fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);
// Start our child containers, if not already started
for (Container child : findChildren()) {
if (!child.getState().isAvailable()) {
child.start();
}
}
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).start(); // 启动管道
}
……..
}
} finally {
unbindThread(oldCCL);
}
if (ok ) {
if (getInstanceManager() == null) {
javax.naming.Context context = null;
if (isUseNaming() && getNamingContextListener() != null) {
context = getNamingContextListener().getEnvContext();
}
Map<String, Map<String, String>> injectionMap = buildInjectionMap(
getIgnoreAnnotations() ? new NamingResources(): getNamingResources());
/** 创建每个应用StandardContext自己的DefaultInstanceManager实例管理器对象 */
/** 并且会从WebAppLoader拿到WebAppClassLoader类加载器,之后此WebApp的应用类都由此ClassLoader加载 */
setInstanceManager(new DefaultInstanceManager(context,
injectionMap, this, this.getClass().getClassLoader()));
getServletContext().setAttribute(
InstanceManager.class.getName(), getInstanceManager());
}
}
try {
// Create context attributes that will be required
if (ok) {
getServletContext().setAttribute(
JarScanner.class.getName(), getJarScanner());
}
// Set up the context init params
mergeParameters(); //把StandardContext中的上下文参数设置到ServletContext中
// Call ServletContainerInitializers
for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :
initializers.entrySet()) {
try {
entry.getKey().onStartup(entry.getValue(),
getServletContext());
} catch (ServletException e) {
// TODO: Log error
ok = false;
break;
}
}
if (ok) {
if (!listenerStart()) { // 启动监听器Listner
log.error( "Error listenerStart");
ok = false;
}
}
try {
if ((manager != null) && (manager instanceof Lifecycle)) {
((Lifecycle) getManager()).start(); // 启动Session管理器Manager
}
// Start ContainerBackgroundProcessor thread
super.threadStart();
} catch(Exception e) {
log.error("Error manager.start()", e);
ok = false;
}
if (ok) {
if (!filterStart()) { // 启动Filter
log.error("Error filterStart");
ok = false;
}
}
if (ok) {
loadOnStartup(findChildren()); // 启动load-on-startup的Servlet
}
} finally {
// Unbinding thread
unbindThread(oldCCL);
}
……..
if (!ok) {
setState(LifecycleState.FAILED);
} else {
setState(LifecycleState.STARTING);
}
}
// 处理StandardContext的configure_start事件,解析WEB应用的WEB-INF/web.xml配置文件
org.apache.catalina.startup.ContextConfig.lifecycleEvent(LifecycleEvent event){
try {
context = (Context) event.getLifecycle();
} catch (ClassCastException e) {
log.error(sm.getString("contextConfig.cce", event.getLifecycle()), e);
return;
}
// Process the event that has occurred
if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
configureStart();
} else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
beforeStart();
}
………
else if (event.getType().equals(Lifecycle.AFTER_DESTROY_EVENT)) {
destroy();
}
}
org.apache.catalina.startup.ContextConfig.configureStart(){
webConfig();
if (!context.getIgnoreAnnotations()) {
applicationAnnotationsConfig();
}
if (ok) {
validateSecurityRoles();
}
if (ok) authenticatorConfig();
………
if (ok)
context.setConfigured(true); // 设置已经配置好的状态
else {
log.error(sm.getString("contextConfig.unavailable"));
context.setConfigured(false);
}
}
org.apache.catalina.startup.ContextConfig.webConfig(){
Set<WebXml> defaults = new HashSet<WebXml>();
// 添加默认的配置(全局:conf/web.xml)
defaults.add(getDefaultWebXmlFragment());
// 创建当前WebApp的web.xml文件WebXml对象
WebXml webXml = createWebXml();
InputSource contextWebXml = getContextWebXmlSource();
parseWebXml(contextWebXml, webXml, false); // 将xml配置解析到WebXml对象中
if (webXml.getMajorVersion() >= 3) {
ServletContext sContext = context.getServletContext();
Map<String,WebXml> fragments = processJarsForWebFragments();
Set<WebXml> orderedFragments = null;
// Only need to process fragments and annotations if metadata is not complete
// 需要处理annotations等的情况
if (!webXml.isMetadataComplete()) {
………
} else {
webXml.merge(defaults); // 合并默认的配置
webXml.configureContext(context); // 解析配置信息到StandardContext中
}
if (ok) {
// Spec does not define an order.
// Use ordered JARs followed by remaining JARs
Set<WebXml> resourceJars = new LinkedHashSet<WebXml>();
if (orderedFragments != null) {
for (WebXml fragment : orderedFragments) {
resourceJars.add(fragment);
}
}
for (WebXml fragment : fragments.values()) {
if (!resourceJars.contains(fragment)) {
resourceJars.add(fragment);
}
}
processResourceJARs(resourceJars);
// See also StandardContext.resourcesStart() for
// WEB-INF/classes/META-INF/resources configuration
}
………
}
} else {
// Apply unmerged web.xml to Context
webXml.merge(defaults);
convertJsps(webXml);
webXml.configureContext(context);
}
}
// 把WebXml对象中的配置信息解析到StandardContext对象中
org.apache.catalina.deploy.WebXml.configureContext(Context context){
context.setPublicId(publicId);
context.setEffectiveMajorVersion(getMajorVersion());
context.setEffectiveMinorVersion(getMinorVersion());
for (Entry<String, String> entry : contextParams.entrySet()) {
context.addParameter(entry.getKey(), entry.getValue()); // 添加上下文参数
}
for (FilterDef filter : filters.values()) {
if (filter.getAsyncSupported() == null) {
filter.setAsyncSupported("false");
}
context.addFilterDef(filter); // 添加过滤器
}
for (FilterMap filterMap : filterMaps) {
context.addFilterMap(filterMap);
}
for (JspPropertyGroup jspPropertyGroup : jspPropertyGroups) {
JspPropertyGroupDescriptor descriptor =
new ApplicationJspPropertyGroupDescriptor(jspPropertyGroup);
context.getJspConfigDescriptor().getJspPropertyGroups().add(
descriptor);
}
for (String listener : listeners) {
context.addApplicationListener(listener); // 添加监听器
}
for (Entry<String, String> entry : localeEncodingMappings.entrySet()) {
context.addLocaleEncodingMappingParameter(entry.getKey(),
entry.getValue());
}
// Prevents IAE
if (loginConfig != null) {
context.setLoginConfig(loginConfig);
}
for (ServletDef servlet : servlets.values()) {
Wrapper wrapper = context.createWrapper(); // 根据Servlet构建包装器Wrapper
if (servlet.getLoadOnStartup() != null) {
wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
}
if (servlet.getEnabled() != null) {
wrapper.setEnabled(servlet.getEnabled().booleanValue());
}
wrapper.setName(servlet.getServletName());
Map<String,String> params = servlet.getParameterMap();
for (Entry<String, String> entry : params.entrySet()) {
wrapper.addInitParameter(entry.getKey(), entry.getValue());
}
wrapper.setRunAs(servlet.getRunAs());
Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs();
for (SecurityRoleRef roleRef : roleRefs) {
wrapper.addSecurityReference(
roleRef.getName(), roleRef.getLink());
}
wrapper.setServletClass(servlet.getServletClass());
MultipartDef multipartdef = servlet.getMultipartDef();
if (multipartdef != null) {
if (multipartdef.getMaxFileSize() != null &&
multipartdef.getMaxRequestSize()!= null &&
multipartdef.getFileSizeThreshold() != null) {
wrapper.setMultipartConfigElement(new MultipartConfigElement(
multipartdef.getLocation(),
Long.parseLong(multipartdef.getMaxFileSize()),
Long.parseLong(multipartdef.getMaxRequestSize()),
Integer.parseInt(
multipartdef.getFileSizeThreshold())));
} else {
wrapper.setMultipartConfigElement(new MultipartConfigElement(
multipartdef.getLocation()));
}
}
if (servlet.getAsyncSupported() != null) {
wrapper.setAsyncSupported(
servlet.getAsyncSupported().booleanValue());
}
wrapper.setOverridable(servlet.isOverridable());
context.addChild(wrapper); // 往Context中添加子容器Wrapper,并启动Wrapper容器
}
for (Entry<String, String> entry : servletMappings.entrySet()) {
context.addServletMapping(entry.getKey(), entry.getValue());
}
if (sessionConfig != null) {
if (sessionConfig.getSessionTimeout() != null) {
context.setSessionTimeout(
sessionConfig.getSessionTimeout().intValue());
}
}
for (Entry<String, String> entry : taglibs.entrySet()) {
TaglibDescriptor descriptor = new ApplicationTaglibDescriptor(
entry.getValue(), entry.getKey());
context.getJspConfigDescriptor().getTaglibs().add(descriptor);
}
for (String welcomeFile : welcomeFiles) {
if (welcomeFile != null && welcomeFile.length() > 0) {
context.addWelcomeFile(welcomeFile);
}
}
}
// 启动监听器Listener
public boolean listenerStart() {
if (log.isDebugEnabled())
log.debug("Configuring application event listeners");
// Instantiate the required listeners
String listeners[] = findApplicationListeners();
Object results[] = new Object[listeners.length];
boolean ok = true;
for (int i = 0; i < results.length; i++) {
if (getLogger().isDebugEnabled())
getLogger().debug(" Configuring event listener class '" +
listeners[i] + "'");
try {
results[i] = instanceManager.newInstance(listeners[i]);
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
getLogger().error
(sm.getString("standardContext.applicationListener",
listeners[i]), t);
ok = false;
}
}
if (!ok) {
getLogger().error(sm.getString("standardContext.applicationSkipped"));
return (false);
}
// Sort listeners in two arrays
ArrayList<Object> eventListeners = new ArrayList<Object>();
ArrayList<Object> lifecycleListeners = new ArrayList<Object>();
for (int i = 0; i < results.length; i++) {
if ((results[i] instanceof ServletContextAttributeListener)
|| (results[i] instanceof ServletRequestAttributeListener)
|| (results[i] instanceof ServletRequestListener)
|| (results[i] instanceof HttpSessionAttributeListener)) {
eventListeners.add(results[i]);
}
if ((results[i] instanceof ServletContextListener)
|| (results[i] instanceof HttpSessionListener)) {
lifecycleListeners.add(results[i]);
}
}
//Listeners may have been added by ServletContextInitializers. Put them after the ones we know about.
for (Object eventListener: getApplicationEventListeners()) {
eventListeners.add(eventListener);
}
setApplicationEventListeners(eventListeners.toArray());
for (Object lifecycleListener: getApplicationLifecycleListeners()) {
lifecycleListeners.add(lifecycleListener);
}
setApplicationLifecycleListeners(lifecycleListeners.toArray());
// Send application start events
if (getLogger().isDebugEnabled())
getLogger().debug("Sending application start events");
// Ensure context is not null
getServletContext();
context.setNewServletContextListenerAllowed(false);
Object instances[] = getApplicationLifecycleListeners();
if (instances == null)
return (ok);
// 创建一个ServletContextEvent
ServletContextEvent event = new ServletContextEvent(getServletContext());
for (int i = 0; i < instances.length; i++) {
if (instances[i] == null)
continue;
if (!(instances[i] instanceof ServletContextListener))
continue;
ServletContextListener listener =
(ServletContextListener) instances[i];
try {
fireContainerEvent("beforeContextInitialized", listener);
// 执行监听器Listener
listener.contextInitialized(event);
fireContainerEvent("afterContextInitialized", listener);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
fireContainerEvent("afterContextInitialized", listener);
getLogger().error
(sm.getString("standardContext.listenerStart",
instances[i].getClass().getName()), t);
ok = false;
}
}
return (ok);
}
// 启动过滤器Filter
org.apache.catalina.core.StandardContext.filterStart(){
if (getLogger().isDebugEnabled())
getLogger().debug("Starting filters");
boolean ok = true;
synchronized (filterConfigs) {
filterConfigs.clear();
Iterator<String> names = filterDefs.keySet().iterator();
while (names.hasNext()) {
String name = names.next();
if (getLogger().isDebugEnabled())
getLogger().debug(" Starting filter '" + name + "'");
ApplicationFilterConfig filterConfig = null;
try {
filterConfig = new ApplicationFilterConfig(this, filterDefs.get(name));
filterConfigs.put(name, filterConfig);
} catch (Throwable t) {
t = ExceptionUtils.unwrapInvocationTargetException(t);
ExceptionUtils.handleThrowable(t);
getLogger().error
(sm.getString("standardContext.filterStart", name), t);
ok = false;
}
}
}
return (ok);
}
// 启动load-on-startup的Servlet
// 默认有org.apache.catalina.servlets.DefaultServlet;org.apache.jasper.servlet.JspServlet
org.apache.catalina.core.StandardContext.loadOnStartup(Container[] children){
TreeMap<Integer, ArrayList<Wrapper>> map =
new TreeMap<Integer, ArrayList<Wrapper>>();
for (int i = 0; i < children.length; i++) {
Wrapper wrapper = (Wrapper) children[i];
int loadOnStartup = wrapper.getLoadOnStartup();
if (loadOnStartup < 0) //判断是否是启动初始化Servlet
continue;
Integer key = Integer.valueOf(loadOnStartup);
ArrayList<Wrapper> list = map.get(key);
if (list == null) {
list = new ArrayList<Wrapper>();
map.put(key, list);
}
list.add(wrapper);
}
// Load the collected "load on startup" servlets
for (ArrayList<Wrapper> list : map.values()) {
for (Wrapper wrapper : list) {
try {
wrapper.load();
} catch (ServletException e) {
getLogger().error(sm.getString("standardWrapper.loadException",
getName()), StandardWrapper.getRootCause(e));
// NOTE: load errors (including a servlet that throws
// UnavailableException from tht init() method) are NOT
// fatal to application startup
}
}
}
}
org.apache.catalina.core.StandardWrapper.load(){
instance = loadServlet(); // 具体不在讲解
if (!instanceInitialized) {
initServlet(instance); // 初始化
}
if (isJspServlet) {
StringBuilder oname =
new StringBuilder(MBeanUtils.getDomain(getParent()));
oname.append(":type=JspMonitor,name=");
oname.append(getName());
oname.append(getWebModuleKeyProperties());
try {
jspMonitorON = new ObjectName(oname.toString());
Registry.getRegistry(null, null)
.registerComponent(instance, jspMonitorON, null);
} catch( Exception ex ) {
log.info("Error registering JSP monitoring with jmx " +
instance);
}
}
}
(7) 第七层 :向Mapper注册主机及其子容器
org.apache.catalina.connector.MapperListener.startInternal(){
setState(LifecycleState.STARTING);
findDefaultHost(); // 查找并设置默认主机
Engine engine = (Engine) connector.getService().getContainer();
addListeners(engine);
Container[] conHosts = engine.findChildren();
for (Container conHost : conHosts) {
Host host = (Host) conHost;
if (!LifecycleState.NEW.equals(host.getState())) {
// Registering the host will register the context and wrappers
registerHost(host); // 将主机注册到MapperListener
}
}
}
org.apache.catalina.connector.MapperListener.registerHost(Host host){
String[] aliases = host.findAliases();
mapper.addHost(host.getName(), aliases, host); // 添加主机
for (Container container : host.findChildren()) {
if (container.getState().isAvailable()) {
registerContext((Context) container); // 注册App上下文
}
}
if(log.isDebugEnabled()) {
log.debug(sm.getString("mapperListener.registerHost",
host.getName(), domain, connector));
}
}
org.apache.catalina.connector.MapperListener.registerContext(Context context){
String contextPath = context.getPath();
if ("/".equals(contextPath)) {
contextPath = "";
}
Container host = context.getParent();
javax.naming.Context resources = context.getResources();
String[] welcomeFiles = context.findWelcomeFiles();
mapper.addContextVersion(host.getName(), host, contextPath, // 添加App上下文
context.getWebappVersion(), context, welcomeFiles, resources);
for (Container container : context.findChildren()) {
registerWrapper((Wrapper) container); // 注册包装器
}
if(log.isDebugEnabled()) {
log.debug(sm.getString("mapperListener.registerContext",
contextPath, connector));
}
}
org.apache.catalina.connector.MapperListener.registerWrapper(Wrapper wrapper){
String wrapperName = wrapper.getName();
Context context = (Context) wrapper.getParent();
String contextPath = context.getPath();
if ("/".equals(contextPath)) {
contextPath = "";
}
String version = ((Context) wrapper.getParent()).getWebappVersion();
String hostName = context.getParent().getName();
String[] mappings = wrapper.findMappings();
for (String mapping : mappings) {
boolean jspWildCard = (wrapperName.equals("jsp")
&& mapping.endsWith("/*"));
mapper.addWrapper(hostName, contextPath, version, mapping, wrapper, // 添加包装器
jspWildCard,
context.isResourceOnlyServlet(wrapperName));
}
if(log.isDebugEnabled()) {
log.debug(sm.getString("mapperListener.registerWrapper",
wrapperName, contextPath, connector));
}
}
(8) 连接器启动特定协议处理器,并启动接收器线程来接收请求
// http11协议连接请求处理器
org.apache.coyote.http11.Http11Protocol.start(){ // 继承基类org.apache.coyote.AbstractProtocol的start
if (getLog().isInfoEnabled())
getLog().info(sm.getString("abstractProtocolHandler.start",
getName()));
try {
endpoint.start(); // org.apache.tomcat.util.net.JIoEndpoint
} catch (Exception ex) {
getLog().error(sm.getString("abstractProtocolHandler.startError",
getName()), ex);
throw ex;
}
}
org.apache.tomcat.util.net.JIoEndpoint.start(){ // 继承基类AbstractEndpoint的start
if (bindState == BindState.UNBOUND) {
bind();
bindState = BindState.BOUND_ON_START;
}
startInternal();
}
org.apache.tomcat.util.net.JIoEndpoint. startInternal (){
if (!running) {
running = true;
paused = false;
// Create worker collection
if (getExecutor() == null) {
createExecutor(); // 创建线程池执行器
}
initializeConnectionLatch();
startAcceptorThreads(); // 启动接收线程
// Start async timeout thread
Thread timeoutThread = new Thread(new AsyncTimeout(),
getName() + "-AsyncTimeout");
timeoutThread.setPriority(threadPriority);
timeoutThread.setDaemon(true);
timeoutThread.start();
}
}
org.apache.tomcat.util.net.JIoEndpoint. startAcceptorThreads (){
int count = getAcceptorThreadCount();
acceptors = new Acceptor[count];
for (int i = 0; i < count; i++) {
acceptors[i] = createAcceptor(); // 创建接收器Acceptor
Thread t = new Thread(acceptors[i], getName() + "-Acceptor-" + i);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start(); // 启动请求接收线程,至此可以开始接收请求了
}
}
// 创建Acceptor,以便在请求接收线程中运行
org.apache.tomcat.util.net.JIoEndpoint. createAcceptor (){
return new Acceptor(); // org.apache.tomcat.util.net.JIoEndpoint.Acceptor
}
3. 请求过程
(1) 第一层
// 请求接收线程Acceptor接收请求
org.apache.tomcat.util.net.JIoEndpoint.Acceptor.run(){
int errorDelay = 0;
while (running) {
……
try {
countUpOrAwaitConnection();
Socket socket = null;
try {
// 客户端请求socket,默认监听8080端口请求
socket = serverSocketFactory.acceptSocket(serverSocket);
}
……
if (running && !paused && setSocketOptions(socket)) {
// Hand this socket off to an appropriate processor
if (!processSocket(socket)) {
countDownConnection();
// Close socket right away
closeSocket(socket);
}
} else {
countDownConnection();
// Close socket right away
closeSocket(socket);
}
}
}
state = AcceptorState.ENDED;
}
}
(2) 第二层
// 请求接收线程把接收到的请求交给请求处理线程池处理
org.apache.tomcat.util.net.JIoEndpoint.processSocket(Socket socket) {
try {
// 包装成wrapper
SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
// 包装成SocketProcessor交给线程池处理,当前线程不处理以便接收下一个到达的请求
getExecutor().execute(new SocketProcessor(wrapper));
} catch (RejectedExecutionException x) {
log.warn("Socket processing request was rejected for:"+socket,x);
return false;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// This means we got an OOM or similar creating a thread, or that
// the pool and its queue are full
log.error(sm.getString("endpoint.process.fail"), t);
return false;
}
return true;
}
(3) 第三层
// 请求处理线程池起一个线程SocketProcessor来处理请求
org.apache.tomcat.util.net.JIoEndpoint.SocketProcessor.run(){
boolean launch = false;
synchronized (socket) {
try {
SocketState state = SocketState.OPEN;
……
if ((state != SocketState.CLOSED)) {
if (status == null) {
// 引用外部类对象的成员handler处理请求
state = handler.process(socket, SocketStatus.OPEN);
} else {
state = handler.process(socket,status);
}
}
……
} else if (state == SocketState.OPEN ||
state == SocketState.UPGRADING ||
state == SocketState.UPGRADED){
socket.setKeptAlive(true);
socket.access();
launch = true;
} else if (state == SocketState.LONG) {
socket.access();
waitingRequests.add(socket);
}
} finally {
if (launch) {
try {
getExecutor().execute(new SocketProcessor(socket, SocketStatus.OPEN));
} catch (RejectedExecutionException x) {
log.warn("Socket reprocessing request was rejected for:"+socket,x);
try {
//unable to handle connection at this time
handler.process(socket, SocketStatus.DISCONNECT);
} finally {
countDownConnection();
}
} catch (NullPointerException npe) {
if (running) {
log.error(sm.getString("endpoint.launch.fail"),
npe);
}
}
}
}
}
socket = null;
}
}
(4) 第四层
// Http11Protocol$Http11ConnectionHandler来处理请求
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process
(SocketWrapper<S> socket,SocketStatus status){
Processor<S> processor = connections.remove(socket.getSocket());
if (status == SocketStatus.DISCONNECT && processor == null) {
//nothing more to be done endpoint requested a close
//and there are no object associated with this connection
return SocketState.CLOSED;
}
socket.setAsync(false);
try {
if (processor == null) {
processor = recycledProcessors.poll();
}
if (processor == null) {
// 创建Http11Processor对象,把Http11Protocol的CoyoteAdapter传给Http11Processor
processor = createProcessor();
}
initSsl(socket, processor);
SocketState state = SocketState.CLOSED;
do {
if (status == SocketStatus.DISCONNECT) {
//do nothing here, just wait for it to get recycled
} else if (processor.isAsync() || state == SocketState.ASYNC_END) {
state = processor.asyncDispatch(status);
} else if (processor.isComet()) {
state = processor.event(status);
} else if (processor.isUpgrade()) {
state = processor.upgradeDispatch();
} else {
// 通过Http11Processor 来处理请求
state = processor.process(socket);
}
if (state != SocketState.CLOSED && processor.isAsync()) {
state = processor.asyncPostProcess();
}
if (state == SocketState.UPGRADING) {
// Get the UpgradeInbound handler
UpgradeInbound inbound = processor.getUpgradeInbound();
// Release the Http11 processor to be re-used
release(socket, processor, false, false);
// Create the light-weight upgrade processor
processor = createUpgradeProcessor(socket, inbound);
inbound.onUpgradeComplete();
}
} while (state == SocketState.ASYNC_END ||
state == SocketState.UPGRADING);
if (state == SocketState.LONG) {
// In the middle of processing a request/response. Keep the
// socket associated with the processor. Exact requirements
// depend on type of long poll
longPoll(socket, processor);
} else if (state == SocketState.OPEN) {
// In keep-alive but between requests. OK to recycle
// processor. Continue to poll for the next request.
release(socket, processor, false, true);
} else if (state == SocketState.SENDFILE) {
// Sendfile in progress. If it fails, the socket will be
// closed. If it works, the socket will be re-added to the
// poller
release(socket, processor, false, false);
} else if (state == SocketState.UPGRADED) {
// Need to keep the connection associated with the processor
longPoll(socket, processor);
} else {
// Connection closed. OK to recycle the processor.
if (!(processor instanceof UpgradeProcessor)) {
release(socket, processor, true, false);
}
}
return state;
} catch(java.net.SocketException e) {
// SocketExceptions are normal
getLog().debug(sm.getString(
"ajpprotocol.proto.socketexception.debug"), e);
} catch (java.io.IOException e) {
// IOExceptions are normal
getLog().debug(sm.getString(
"ajpprotocol.proto.ioexception.debug"), e);
}
// Future developers: if you discover any other
// rare-but-nonfatal exceptions, catch them here, and log as
// above.
catch (Throwable e) {
ExceptionUtils.handleThrowable(e);
// any other exception or error is odd. Here we log it
// with "ERROR" level, so it will show up even on
// less-than-verbose logs.
getLog().error(sm.getString("ajpprotocol.proto.error"), e);
}
// Don't try to add upgrade processors back into the pool
if (!(processor instanceof UpgradeProcessor)) {
release(socket, processor, true, false);
}
return SocketState.CLOSED;
}
(5) 第五层
// Http11Processor进行请求处理
org.apache.coyote.http11. Http11Processor.process(SocketWrapper<S> socketWrapper){
RequestInfo rp = request.getRequestProcessor();
rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);
// Setting up the I/O
setSocketWrapper(socketWrapper);
getInputBuffer().init(socketWrapper, endpoint);
getOutputBuffer().init(socketWrapper, endpoint);
// Flags
error = false;
keepAlive = true;
comet = false;
openSocket = false;
sendfileInProgress = false;
readComplete = true;
if (endpoint.getUsePolling()) {
keptAlive = false;
} else {
keptAlive = socketWrapper.isKeptAlive();
}
if (disableKeepAlive()) {
socketWrapper.setKeepAliveLeft(0);
}
while (!error && keepAlive && !comet && !isAsync() &&
upgradeInbound == null && !endpoint.isPaused()) {
// Parsing the request header
try {
setRequestLineReadTimeout();
if (!getInputBuffer().parseRequestLine(keptAlive)) {
if (handleIncompleteRequestLineRead()) {
break;
}
}
if (endpoint.isPaused()) {
// 503 - Service unavailable
response.setStatus(503);
error = true;
} else {
request.setStartTime(System.currentTimeMillis());
keptAlive = true;
// Set this every time in case limit has been changed via JMX
request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());
// Currently only NIO will ever return false here
if (!getInputBuffer().parseHeaders()) {
// We've read part of the request, don't recycle it
// instead associate it with the socket
openSocket = true;
readComplete = false;
break;
}
if (!disableUploadTimeout) {
setSocketTimeout(connectionUploadTimeout);
}
}
} catch (IOException e) {
if (getLog().isDebugEnabled()) {
getLog().debug(
sm.getString("http11processor.header.parse"), e);
}
error = true;
break;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (getLog().isDebugEnabled()) {
getLog().debug(
sm.getString("http11processor.header.parse"), t);
}
// 400 - Bad Request
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
if (!error) {
// Setting up filters, and parse some request headers
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
// 准备请求对象
prepareRequest();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString(
"http11processor.request.prepare"), t);
}
// 400 - Internal Server Error
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
}
if (maxKeepAliveRequests == 1) {
keepAlive = false;
} else if (maxKeepAliveRequests > 0 &&
socketWrapper.decrementKeepAlive() <= 0) {
keepAlive = false;
}
// Process the request in the adapter
if (!error) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
// CoyoteAdapter处理请求
adapter.service(request, response);
// Handle when the response was committed before a serious
// error occurred. Throwing a ServletException should both
// set the status to 500 and set the errorException.
// If we fail here, then the response is likely already
// committed, so we can't try and set headers.
if(keepAlive && !error) { // Avoid checking twice.
error = response.getErrorException() != null ||
(!isAsync() &&
statusDropsConnection(response.getStatus()));
}
setCometTimeouts(socketWrapper);
} catch (InterruptedIOException e) {
error = true;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
getLog().error(sm.getString(
"http11processor.request.process"), t);
// 500 - Internal Server Error
response.setStatus(500);
adapter.log(request, response, 0);
error = true;
}
}
// Finish the handling of the request
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
if (!isAsync() && !comet) {
if (error) {
// If we know we are closing the connection, don't drain
// input. This way uploading a 100GB file doesn't tie up the
// thread if the servlet has rejected it.
getInputBuffer().setSwallowInput(false);
}
endRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
// If there was an error, make sure the request is counted as
// and error, and update the statistics counter
if (error) {
response.setStatus(500);
}
request.updateCounters();
if (!isAsync() && !comet || error) {
getInputBuffer().nextRequest();
getOutputBuffer().nextRequest();
}
if (!disableUploadTimeout) {
setSocketTimeout(endpoint.getSoTimeout());
}
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
if (breakKeepAliveLoop(socketWrapper)) {
break;
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (error || endpoint.isPaused()) {
return SocketState.CLOSED;
} else if (isAsync() || comet) {
return SocketState.LONG;
} else if (isUpgrade()) {
return SocketState.UPGRADING;
} else {
if (sendfileInProgress) {
return SocketState.SENDFILE;
} else {
if (openSocket) {
if (readComplete) {
return SocketState.OPEN;
} else {
return SocketState.LONG;
}
} else {
return SocketState.CLOSED;
}
}
}
}
(6) 第六层
// CoyoteAdapter进行请求处理
org.apache.catalina.connector.CoyoteAdapter.service(Request req, Response res){
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
if (request == null) {
// Create objects
request = connector.createRequest();
request.setCoyoteRequest(req);
response = connector.createResponse();
response.setCoyoteResponse(res);
// Link objects
request.setResponse(response);
response.setRequest(request);
// Set as notes
req.setNote(ADAPTER_NOTES, request);
res.setNote(ADAPTER_NOTES, response);
// Set query string encoding
req.getParameters().setQueryStringEncoding
(connector.getURIEncoding());
}
if (connector.getXpoweredBy()) {
response.addHeader("X-Powered-By", POWERED_BY);
}
boolean comet = false;
boolean async = false;
try {
// Parse and set Catalina and configuration specific
// request parameters
req.getRequestProcessor().setWorkerThreadName(Thread.currentThread().getName());
boolean postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
//check valves if we support async
request.setAsyncSupported(
connector.getService().getContainer().getPipeline().isAsyncSupported());
// 请求开始进入Tomcat的容器层处理,先调用StandardEnine管道的第一个Valve
connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);
if (request.isComet()) {
if (!response.isClosed() && !response.isError()) {
if (request.getAvailable() || (request.getContentLength() > 0 && (!request.isParametersParsed()))) {
// Invoke a read event right away if there are available bytes
if (event(req, res, SocketStatus.OPEN)) {
comet = true;
res.action(ActionCode.COMET_BEGIN, null);
}
} else {
comet = true;
res.action(ActionCode.COMET_BEGIN, null);
}
} else {
// Clear the filter chain, as otherwise it will not be reset elsewhere
// since this is a Comet request
request.setFilterChain(null);
}
}
}
AsyncContextImpl asyncConImpl = (AsyncContextImpl)request.getAsyncContext();
if (asyncConImpl != null) {
async = true;
} else if (!comet) {
request.finishRequest();
response.finishResponse();
if (postParseSuccess &&
request.getMappingData().context != null) {
((Context) request.getMappingData().context).logAccess(
request, response,
System.currentTimeMillis() - req.getStartTime(),
false);
}
req.action(ActionCode.POST_REQUEST , null);
}
} catch (IOException e) {
// Ignore
} finally {
req.getRequestProcessor().setWorkerThreadName(null);
// Recycle the wrapper request and response
if (!comet && !async) {
request.recycle();
response.recycle();
} else {
// Clear converters so that the minimum amount of memory
// is used by this processor
request.clearEncoders();
response.clearEncoders();
}
}
}
(7) 第七层
// 调用StandardEngine管道的基础阀门StandardEngineValve
org.apache.catalina.core.StandardEngineValve.invoke(Request request, Response response){
Host host = request.getHost();
if (host == null) {
response.sendError
(HttpServletResponse.SC_BAD_REQUEST,
sm.getString("standardEngine.noHost",
request.getServerName()));
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
}
// Ask this Host to process this request
// 调用StandardHost管道的第一个阀门
host.getPipeline().getFirst().invoke(request, response);
}
// 调用StandardHost管道的基础阀门StandardHostValve
org.apache.catalina.core.StandardHostValve.invoke(Request request, Response response){
Context context = request.getContext();
if (context == null) {
response.sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
sm.getString("standardHost.noContext"));
return;
}
if( context.getLoader() != null ) {
if (Globals.IS_SECURITY_ENABLED) {
PrivilegedAction<Void> pa = new PrivilegedSetTccl(
context.getLoader().getClassLoader());
AccessController.doPrivileged(pa);
} else {
// 线程上下文类加载器切换成当前WebApp的类加载器
Thread.currentThread().setContextClassLoader
(context.getLoader().getClassLoader());
}
}
if (asyncAtStart || context.fireRequestInitEvent(request)) {
try {
// 调用StandardContext管道的第一个阀门
context.getPipeline().getFirst().invoke(request, response);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
throwable(request, response, t);
}
}
// Access a session (if present) to update last accessed time, based on a
// strict interpretation of the specification
if (ACCESS_SESSION) {
request.getSession(false);
}
if (Globals.IS_SECURITY_ENABLED) {
PrivilegedAction<Void> pa = new PrivilegedSetTccl(
StandardHostValve.class.getClassLoader());
AccessController.doPrivileged(pa);
} else {
// 还原StandardClassLoader类加载器为线程上文类加载器
Thread.currentThread().setContextClassLoader
(StandardHostValve.class.getClassLoader());
};
}
// 调用StandardContext管道的基础阀门StandardContextValve
org.apache.catalina.core.StandardContextValve.invoke(Request request, Response response){
MessageBytes requestPathMB = request.getRequestPathMB();
// 禁止访问特点目录
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
Wrapper wrapper = request.getWrapper();
if (wrapper == null || wrapper.isUnavailable()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
try {
response.sendAcknowledgement();
} catch (IOException ioe) {
container.getLogger().error(sm.getString(
"standardContextValve.acknowledgeException"), ioe);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
}
// 调用StandardWrapper管道的第一个阀门
wrapper.getPipeline().getFirst().invoke(request, response);
}
// 调用StandardWrapper管道的基础阀门StandardWrapperValve
org.apache.catalina.core.StandardWrapperValve.invoke(Request request, Response response){
boolean unavailable = false;
Throwable throwable = null;
long t1=System.currentTimeMillis();
requestCount++;
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
Context context = (Context) wrapper.getParent();
……
try {
if (!unavailable) {
// 获取StandardWrapper对应的Servlet实例
servlet = wrapper.allocate();
}
}
// 创建过滤器链
ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);
request.setComet(false);
try {
if ((servlet != null) && (filterChain != null)) {
// Swallow output if needed
if (context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
if (request.isAsyncDispatching()) {
//TODO SERVLET3 - async
((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch();
} else if (comet) {
filterChain.doFilterEvent(request.getEvent());
request.setComet(true);
} else {
// 执行过滤器链
filterChain.doFilter(request.getRequest(), response.getResponse());
}
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
context.getLogger().info(log);
}
}
} else {
if (request.isAsyncDispatching()) {
//TODO SERVLET3 - async
((AsyncContextImpl)request.getAsyncContext()).doInternalDispatch();
} else if (comet) {
request.setComet(true);
filterChain.doFilterEvent(request.getEvent());
} else {
filterChain.doFilter
(request.getRequest(), response.getResponse());
}
}
}
}
…….
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
}
……
}
// 调用过滤器链ApplicationFilterChain
org.apache.catalina.core.ApplicationFilterChain.doFilter(ServletRequest request, ServletResponse response){
……
internalDoFilter(request,response);
……
}
// 在这个方法中调用过滤器的doFilter和servlet的service方法
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ServletRequest request, ServletResponse response){
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = null;
try {
filter = filterConfig.getFilter();
…….
} else {
// 执行过滤器Filter
filter.doFilter(request, response, this);
}
support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT,
filter, request, response);
}
…….
}
try {
……..
........
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse)) {
if( Globals.IS_SECURITY_ENABLED ) {
final ServletRequest req = request;
final ServletResponse res = response;
Principal principal =
((HttpServletRequest) req).getUserPrincipal();
Object[] args = new Object[]{req, res};
SecurityUtil.doAsPrivilege("service",servlet,classTypeUsedInService, args,principal);
} else {
// 执行Servlet
servlet.service(request, response);
}
} else {
servlet.service(request, response);
}
support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT,
servlet, request, response);
}
……….
} finally {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}
4. 关闭过程
// 服务器启动之后进入await方法,等待停机命令
org.apache.catalina.startup.Catalina.start(){
// 启动StandardServer服务器
getServer().start();
if (await) {
await(); // 调用StandardServer的await方法,等待停机命令
stop(); // 从服务器的await方法退出后就执行停机命令
}
}
// 通过ServerSocket监听对服务器的停机命令,如果没有停机命令,main线程就会阻塞在这里
org.apache.catalina.core.StandardServer.await(){
// Set up a server socket to wait on
try {
// 创建一个用于监听指定端口关机请求的serverSocket, 默认8005端口
awaitSocket = new ServerSocket(port, 1,
InetAddress.getByName(address));
} catch (IOException e) {
log.error("StandardServer.await: create[" + address+ ":" + port+ "]: ", e);
return;
}
try {
awaitThread = Thread.currentThread();
// 一直循环
while (!stopAwait) {
ServerSocket serverSocket = awaitSocket;
if (serverSocket == null) {
break;
}
Socket socket = null;
StringBuilder command = new StringBuilder();
try{
Stream stream;
try{
// 等待关机请求,默认监听8005端口关机请求,如果没有请求,main线程就会阻塞在这里
socket = serverSocket.accept();
socket.setSoTimeout(10 * 1000); // Ten seconds
stream = socket.getInputStream();
}
}
// 获取请求内容
int expected = 1024; // Cut off to avoid DoS attack
while (expected < shutdown.length()) {
if (random == null)
random = new Random();
expected += (random.nextInt() % 1024);
}
while (expected > 0) {
int ch = -1;
try {
ch = stream.read();
} catch (IOException e) {
log.warn("StandardServer.await: read: ", e);
ch = -1;
}
if (ch < 32) // Control character or EOF terminates loop
break;
command.append((char) ch);
expected--;
}
// 是否与停机命令SHUTDOWN相同
boolean match = command.toString().equals(shutdown);
if (match) {
log.info(sm.getString("standardServer.shutdownViaPort"));
// 与停机命令相同则退出循环,从而退出await方法,回到catalina的start方法
break;
} else
log.warn("StandardServer.await: Invalid command '"
+ command.toString() + "' received");
}
} finally {
……..
}
}
// 跳出await方法之后调用stop方法关闭服务器
org.apache.catalina.startup.Catalina.stop(){
try {
if (useShutdownHook) {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
LogManager logManager = LogManager.getLogManager();
if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook(
true);
}
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// This will fail on JDK 1.2. Ignoring, as Tomcat can run
// fine without the shutdown hook.
}
try {
Server s = getServer();
LifecycleState state = s.getState();
if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0
&& LifecycleState.DESTROYED.compareTo(state) >= 0) {
// Nothing to do. stop() was already called
} else {
s.stop(); // 调用StandardServer的stop方法关闭服务器
s.destroy(); // 调用StandardServer的destory方法销毁资源
}
} catch (LifecycleException e) {
log.error("Catalina.stop", e);
}
}