Catalina
Tomcat里的Server由 org.apache.catalina.startup.Catalina管理。Catalina类里面由 load、start、stop三个方法用来管理整个服务器的生命周期。
1、load:用于根据 conf/server.xml 文件创建Server、并调用Server的init方法进行初始化。
2、start:用于启动服务器。
3、stop:停止服务器。
start、stop方法在内部会调用Server的start和stop方法,load方法调用Server的init方法。
Server的start方法会调用Service中的start方法,Service中的start会调用Connectors和Container中的start方法。
org.apache.catalina.startup.Catalina
// 主要看 Await、load、start、stop方法
Await方法
// 设置 await值,会在start方法中服务器启动完成后来判断是否进入等待状态
public void setAwait(boolean b) {await = b;
}
Load方法
// org.apache.catalina.startup.Catalina
public void load() {// 已经加载就返回if (loaded) {return;}// 设置加载状态loaded = true;long t1 = System.nanoTime();initDirs();// Before digester - it may be neededinitNaming();// Create and execute our Digester// 通过 digester 解析 server.xml 配置文件Digester digester = createStartDigester();InputSource inputSource = null;InputStream inputStream = null;File file = null;try {try {// 指定了 conf/server.xml file = configFile();inputStream = new FileInputStream(file);inputSource = new InputSource(file.toURI().toURL().toString());}if (inputStream == null) {try {inputStream = getClass().getClassLoader().getResourceAsStream(getConfigFile());inputSource = new InputSource(getClass().getClassLoader().getResource(getConfigFile()).toString());}}if (inputStream == null) {// 尝试加载 server-embed.xml try {inputStream = getClass().getClassLoader().getResourceAsStream("server-embed.xml");inputSource = new InputSource(getClass().getClassLoader().getResource("server-embed.xml").toString());}}// 依旧找不到文件,返回if (inputStream == null || inputSource == null) {return;}try {inputSource.setByteStream(inputStream);digester.push(this);// 解析 xmldigester.parse(inputSource);}} finally {if (inputStream != null) {try {inputStream.close();} catch (IOException e) {// Ignore}}}getServer().setCatalina(this);getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());// Stream redirectioninitStreams();// Start the new servertry {getServer().init();}
}
简化后的 load方法:
Digester digester = createStartDigester();
File file = configFile();
inputStream = new FileInputStream(file);
inputSource = new InputSource(file.toURI().toURL().toString());
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource);
getServer().setCatalina(this);
getServer().init();
Digester 查相关资料:Java解析xml主要由DOM4J(一次读取到内存并解析)、SAX(一次解析一部分),digester本身采用SAX的解析方式,并提供了一层包装,对使用者更加友好,后来独立出来成为apache的Commons下面的一个单独的子项目。
Start方法
/*** Start a new server instance.*/
public void start() {if (getServer() == null) {load();}// Start the new servertry {getServer().start();} catch (LifecycleException e) {return;}// 注册shutdown钩子函数if (useShutdownHook) {if (shutdownHook == null) {shutdownHook = new CatalinaShutdownHook();}Runtime.getRuntime().addShutdownHook(shutdownHook);LogManager logManager = LogManager.getLogManager();if (logManager instanceof ClassLoaderLogManager) {((ClassLoaderLogManager) logManager).setUseShutdownHook(false);}}if (await) {await();stop();}
}
Stop方法
/*** Stop an existing server instance.*/
public void 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);}// 关闭服务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();s.destroy();}}