林芝企业网站建设公司,一个空间如何做多个网站,网络营销都有哪些内容,织梦网站密码忘记了【0】README 1#xff09;本文部分文字描述转自“how tomcat works”#xff0c;旨在学习“tomcat(17)启动tomcat”的相关知识#xff1b;2#xff09;本文重点关注启动Tomcat时会用到的两个类#xff0c;分别是Catalina类和 Bootstrap类#xff1b;#xff08;干货——…【0】README
1本文部分文字描述转自“how tomcat works”旨在学习“tomcat(17)启动tomcat”的相关知识2本文重点关注启动Tomcat时会用到的两个类分别是Catalina类和 Bootstrap类干货——引入tomcat启动时用到了两个类分别是Catalina类和 Bootstrap类2.1org.apache.catalina.startup.Catalina类用于启动和关闭Server对象并负责解析Tomcat 配置文件 server.xml 2.2org.apache.catalina.startup.Bootstrap类是一个入口点负责创建 Catalina实例并调用其 process()方法 3理论上这两个类可以合二为一但为了支持tomcat的多种运行模式故提供了多种启动类4用户只需要运行相应的批处理文件或shell 脚本即可启动或关闭tomcat5本文会intro 如何在Windows平台 和 UNIX/Linux 平台上运行tomcat6本文总结了 tomcat启动的调用过程非常干货不得不感慨本篇博文产自于收获的季节.【1】Catalina类org.apache.catalina.startup.Catalina1intro它包含一个Digester类用于解析位于 %CATALINA_HOME%/conf 目录下的server.xml 文件理解到tomcat15中 向Digester对象添加规则的原理后就可以自行配置tomcat了干货——理解到tomcat15中 向Digester对象添加规则的原理后就可以自行配置tomct了tomcat(15)Digester库1.1该类还封装了一个Server对象服务器组件你是否有印象该对象有一个Service对象服务组件你是否有印象干货——服务器组件服务组件参见tomcat(14)服务器组件和服务组件 1.2Service对象包含有一个Servlet容器和一个或多个连接器。所以可以使用Catalina类来启动或关闭Server对象 2可以通过实例化Catalina类并调用其process()方法来运行tomcat3universe case即使Catalina类提供了main()方法作为程序的入口点也需要使用Bootstrap类来实例化process()方法如下所示public static void main(String args[]) { // org.apache.catalina.startup.Catalina.main().(new Catalina()).process(args);}public void process(String args[]) { // org.apache.catalina.startup.Catalina.process().setCatalinaHome();setCatalinaBase();try {if (arguments(args)) //highlight line.execute();} catch (Exception e) {e.printStackTrace(System.out);}}
protected void setCatalinaHome() {if (System.getProperty(catalina.home) ! null)return;System.setProperty(catalina.home,System.getProperty(user.dir));}protected void setCatalinaBase() {if (System.getProperty(catalina.base) ! null)return;System.setProperty(catalina.base,System.getProperty(catalina.home));}对以上代码的分析Analysisstep1process()方法设置了两个系统属性catalina.home and catalina.base.catalina.home默认值均为user.dir 属性的值 step2catalina.base catalina.home 所以他们都与 user.dir 属性的值相同 step3随后process()方法会调用 arguments()方法(highlight line)并传入参数列表 step4intro to arguments()方法arguments()方法处理命令行参数如果Catalina对象能够继续处理的话arguments()方法返回true protected boolean arguments(String args[]) {boolean isConfig false;if (args.length 1) {usage();return (false);}for (int i 0; i args.length; i) {if (isConfig) {configFile args[i];isConfig false;} else if (args[i].equals(-config)) {isConfig true;} else if (args[i].equals(-debug)) {debug true;} else if (args[i].equals(-nonaming)) {useNaming false;} else if (args[i].equals(-help)) {usage();return (false);} else if (args[i].equals(start)) {starting true;} else if (args[i].equals(stop)) {stopping true;} else {usage();return (false);}}return (true);}
protected void usage() {System.out.println(usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] [ -debug ] [ -nonaming ] { start | stop });} step5process()方法会检查arguments()的返回值是否为true若为true则调用execute()方法该方法会调用start()方法来启动tomcat 或调用stop()方法来关闭 tomcat protected void execute() throws Exception {if (starting)start();else if (stopping)stop();} Attention以上的分析结果都是基于tomcat4的在tomcat5中 会在 process()方法中调用start()方法和 stop()方法Supplement本文习惯性的总结了上述调用过程【1.1】start()方法1源代码如下protected void start() { // org.apache.catalina.startup.Catalina.start().// Setting additional variablesif (!useNaming) {System.setProperty(catalina.useNaming, false);} else {System.setProperty(catalina.useNaming, true);String value org.apache.naming;String oldValue System.getProperty(javax.naming.Context.URL_PKG_PREFIXES);if (oldValue ! null) {value value : oldValue;} // String URL_PKG_PREFIXES java.naming.factory.url.pkgs;System.setProperty(javax.naming.Context.URL_PKG_PREFIXES, value);value System.getProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY);if (value null) {System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY,org.apache.naming.java.javaURLContextFactory);}}// Create and execute our DigesterDigester digester createStartDigester();File file configFile();try {InputSource is new InputSource(file:// file.getAbsolutePath());FileInputStream fis new FileInputStream(file);is.setByteStream(fis);digester.push(this);digester.parse(is);fis.close();} catch (Exception e) {System.out.println(Catalina.start using configFile() : e);e.printStackTrace(System.out);System.exit(1);}// If a SecurityManager is being used, set properties for// checkPackageAccess() and checkPackageDefinitionif( System.getSecurityManager() ! null ) {String access Security.getProperty(package.access);if( access ! null access.length() 0 )access ,;elseaccess sun.,;Security.setProperty(package.access,access org.apache.catalina.,org.apache.jasper.);String definition Security.getProperty(package.definition);if( definition ! null definition.length() 0 )definition ,;elsedefinition sun.,;Security.setProperty(package.definition,// FIX ME package javax. was removed to prevent HotSpot// fatal internal errorsdefinition java.,org.apache.catalina.,org.apache.jasper.,org.apache.coyote.);}// Replace System.out and System.err with a custom PrintStreamSystemLogHandler log new SystemLogHandler(System.out);System.setOut(log);System.setErr(log);Thread shutdownHook new CatalinaShutdownHook();// Start the new serverif (server instanceof Lifecycle) {try {server.initialize();((Lifecycle) server).start();try {// Register shutdown hookRuntime.getRuntime().addShutdownHook(shutdownHook);} catch (Throwable t) {// This will fail on JDK 1.2. Ignoring, as Tomcat can run// fine without the shutdown hook.}// Wait for the server to be told to shut downserver.await();} catch (LifecycleException e) {System.out.println(Catalina.start: e);e.printStackTrace(System.out);if (e.getThrowable() ! null) {System.out.println(----- Root Cause -----);e.getThrowable().printStackTrace(System.out);}}}// Shut down the serverif (server instanceof Lifecycle) {try {try {// Remove the ShutdownHook first so that server.stop() // doesnt get invoked twiceRuntime.getRuntime().removeShutdownHook(shutdownHook);} catch (Throwable t) {// This will fail on JDK 1.2. Ignoring, as Tomcat can run// fine without the shutdown hook.}((Lifecycle) server).stop();} catch (LifecycleException e) {System.out.println(Catalina.stop: e);e.printStackTrace(System.out);if (e.getThrowable() ! null) {System.out.println(----- Root Cause -----);e.getThrowable().printStackTrace(System.out);}}}} 对以上代码的分析Analysisstep1该方法会创建一个Digester实例来解析server.xml(tomcat配置文件)在解析server.xml文件之前该方法会调用 Digester.push()方法传入当前的Catalina对象这样Catalina对象就成了Digester对象的内部栈中的第一个对象 step2解析server.xml文件后会使变量Server引用一个Server对象默认是 org.apache.catalina.core.StandardServer类型的对象 step3然后start()方法会调用Server.initialize()方法 和 start()方法 step4接着Catalina.start()方法会调用server对象的await方法Server对象会使用一个专用的线程来等待关闭命令await()方法会一直等待直到接收到正确的关闭命令 step5当await()方法返回时Catalina.start()方法会调用Server.stop()方法从而关闭Server对象和其它的组件 AttentionA1此外start方法还会利用关闭钩子确保用户突然退出应用程序时会执行Server.stop()方法 A2start()方法会调用了createStartDigester 方法创建Digester对象createStartDigester()方法的源码如下 protected Digester createStartDigester() {// Initialize the digesterDigester digester new Digester();digester.setClassLoader(StandardServer.class.getClassLoader());if (debug)digester.setDebug(999);digester.setValidating(false);// Configure the actions we will be usingdigester.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 elementclassName);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);digester.addObjectCreate(Server/Service/Listener,null, // MUST be specified in the elementclassName);digester.addSetProperties(Server/Service/Listener);digester.addSetNext(Server/Service/Listener,addLifecycleListener,org.apache.catalina.LifecycleListener);digester.addObjectCreate(Server/Service/Connector,org.apache.catalina.connector.http.HttpConnector,className);digester.addSetProperties(Server/Service/Connector);digester.addSetNext(Server/Service/Connector,addConnector,org.apache.catalina.Connector);digester.addObjectCreate(Server/Service/Connector/Factory,org.apache.catalina.net.DefaultServerSocketFactory,className);digester.addSetProperties(Server/Service/Connector/Factory);digester.addSetNext(Server/Service/Connector/Factory,setFactory,org.apache.catalina.net.ServerSocketFactory);digester.addObjectCreate(Server/Service/Connector/Listener,null, // MUST be specified in the elementclassName);digester.addSetProperties(Server/Service/Connector/Listener);digester.addSetNext(Server/Service/Connector/Listener,addLifecycleListener,org.apache.catalina.LifecycleListener);// Add RuleSets for nested elementsdigester.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/Default));digester.addRuleSet(new NamingRuleSet(Server/Service/Engine/DefaultContext/));digester.addRuleSet(new ContextRuleSet(Server/Service/Engine/Host/Default));digester.addRuleSet(new NamingRuleSet(Server/Service/Engine/Host/DefaultContext/));digester.addRuleSet(new ContextRuleSet(Server/Service/Engine/Host/));digester.addRuleSet(new NamingRuleSet(Server/Service/Engine/Host/Context/));digester.addRule(Server/Service/Engine,new SetParentClassLoaderRule(digester,parentClassLoader));return (digester);} 【1.2】stop()方法1introstop()方法用来关闭Catalina和Server对象2源代码protected void stop() { //org.apache.catalina.startup.Catalina.stop().// Create and execute our DigesterDigester digester createStopDigester();File file configFile();try {InputSource is new InputSource(file:// file.getAbsolutePath());FileInputStream fis new FileInputStream(file);is.setByteStream(fis);digester.push(this);digester.parse(is);fis.close();} catch (Exception e) {System.out.println(Catalina.stop: e);e.printStackTrace(System.out);System.exit(1);}// Stop the existing servertry {Socket socket new Socket(127.0.0.1, server.getPort());OutputStream stream socket.getOutputStream();String shutdown server.getShutdown();for (int i 0; i shutdown.length(); i)stream.write(shutdown.charAt(i));stream.flush();stream.close();socket.close();} catch (IOException e) {System.out.println(Catalina.stop: e);e.printStackTrace(System.out);System.exit(1);}}
protected Digester createStopDigester() {// Initialize the digesterDigester digester new Digester();if (debug)digester.setDebug(999);// Configure the rules we need for shutting downdigester.addObjectCreate(Server,org.apache.catalina.core.StandardServer,className);digester.addSetProperties(Server);digester.addSetNext(Server,setServer,org.apache.catalina.Server);return (digester);
}AttentionA1stop()方法调用createStopDigester()方法来创建一个 Digester实例并调用该实例的push()方法并将当前Catalina对象压入到 Digester对象的内部栈中使用Digester对象解析tomcat 的配置文件 A2然后stop()方法会向正在运行的Server对象发送关闭命令以关闭Server对象 【1.3】启动Digester对象1introCatalina.createStartDigester方法创建了一个 Digester实例然后为其添加规则以解析server.xml文件server.xml文件用来配置 tomcat位于 %CATALINA_HOME%/conf目录下。添加到Digester对象中的规则是理解tomcat配置的关键不能再干货——添加到Digester对象中的关泽是理解tomcat配置的关键2org.apache.catalina.startup.Catalina.createStartDigester()的源代码如上所示 因为该方法在start(方法中调用我们在分析start方法的时候已经分析过了对createStartDigester方法源代码的分析Analysisstep1该方法会创建org.apache.commons.digester.Digestser类的实例并为其添加规则rules step2前3条规则用于解析 server.xml 文件的server元素。下面是为 server 模式添加的规则因为server元素是跟元素故又称为模式 // Configure the actions we will be usingdigester.addObjectCreate(Server,org.apache.catalina.core.StandardServer,className);digester.addSetProperties(Server);digester.addSetNext(Server,setServer,org.apache.catalina.Server); rule1第1条规则表明在遇到server元素时Digester要创建 StandardServer 类的一个实例 rule2第2条规则表明要对 Server对象的指定属性名设置同名的属性值 rule3第3条规则表明将Server对象压入到 Digester对象的内部栈中并与栈中的下一个对象相关联。 3下一个对象是Catalina实例调用其setServer()方法与 Server对象相关联。那Catalina实例是如何防盗Digester 对象的内部栈中的呢 在start()方法的开始部分在解析 server.xml文件之前会调用 Digester.push()方法将Catalina对象压入栈digester.push(this);【1.4】 关闭Digetster对象1intro to createStopDigester()方法该方法会返回一个 Digester对象来关闭 Server对象protected Digester createStopDigester() { //org.apache.catalina.startup.createStopDigester().// Initialize the digesterDigester digester new Digester();if (debug)digester.setDebug(999);// Configure the rules we need for shutting downdigester.addObjectCreate(Server,org.apache.catalina.core.StandardServer,className);digester.addSetProperties(Server);digester.addSetNext(Server,setServer,org.apache.catalina.Server);return (digester);}Attention与启动Digester对象不同关闭Digester对象只对XML 文档的根元素感兴趣【2】 Bootstrap类org.apache.catalina.startup.Bootstrap1intro该类提供了启动tomcat的入口点2当运行startup.bat 文件或 startup.sh 文件时实际上是调用了该类的main()方法。main方法会创建3个类载入器并实例化Catalina类然后它调用Catalina.process()方法3Bootstrap类的定义如下public final class Bootstrap { private static int debug 0; public static void main(String args[]) {// Set the debug flag appropriatelyfor (int i 0; i args.length; i) {if (-debug.equals(args[i]))debug 1;}// Configure catalina.base from catalina.home if not yet setif (System.getProperty(catalina.base) null)System.setProperty(catalina.base, getCatalinaHome());// Construct the class loaders we will needClassLoader commonLoader null;ClassLoader catalinaLoader null;ClassLoader sharedLoader null;try {File unpacked[] new File[1];File packed[] new File[1];File packed2[] new File[2];ClassLoaderFactory.setDebug(debug);unpacked[0] new File(getCatalinaHome(),common File.separator classes);packed2[0] new File(getCatalinaHome(),common File.separator endorsed);packed2[1] new File(getCatalinaHome(),common File.separator lib);commonLoader ClassLoaderFactory.createClassLoader(unpacked, packed2, null);unpacked[0] new File(getCatalinaHome(),server File.separator classes);packed[0] new File(getCatalinaHome(),server File.separator lib);catalinaLoader ClassLoaderFactory.createClassLoader(unpacked, packed,commonLoader);unpacked[0] new File(getCatalinaBase(),shared File.separator classes);packed[0] new File(getCatalinaBase(),shared File.separator lib);sharedLoader ClassLoaderFactory.createClassLoader(unpacked, packed,commonLoader);} catch (Throwable t) {log(Class loader creation threw exception, t);System.exit(1);}Thread.currentThread().setContextClassLoader(catalinaLoader);// Load our startup class and call its process() methodtry {SecurityClassLoad.securityClassLoad(catalinaLoader);// Instantiate a startup class instanceif (debug 1)log(Loading startup class);Class startupClass catalinaLoader.loadClass(org.apache.catalina.startup.Catalina); //highlight line.Object startupInstance startupClass.newInstance();// Set the shared extensions class loaderif (debug 1)log(Setting startup class properties);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);// Call the process() method //highlight line.if (debug 1)log(Calling startup class process() method);methodName process; //highlight line.paramTypes new Class[1];paramTypes[0] args.getClass();paramValues new Object[1];paramValues[0] args;method startupInstance.getClass().getMethod(methodName, paramTypes);method.invoke(startupInstance, paramValues);} catch (Exception e) {System.out.println(Exception during startup processing);e.printStackTrace(System.out);System.exit(2);}} private static String getCatalinaHome() {return System.getProperty(catalina.home,System.getProperty(user.dir));} private static String getCatalinaBase() {return System.getProperty(catalina.base, getCatalinaHome());} private static void log(String message) {System.out.print(Bootstrap: );System.out.println(message);} private static void log(String message, Throwable exception) {log(message);exception.printStackTrace(System.out);}
}对以上代码的分析AnalysisA1Bootstrap类有4个静态方法两个log()方法getCatalinaHome()方法 和 getCatalinaBase()方法 A2getCatalinaHome()方法其基本含义是如果先前没有设置过catalina.home 属性的值它就返回 user.dir属性的值 A3 getCatalinaBase()方法基本含义是如果catalina.base属性的值为空则返回 catalina.home属性的值 A4Bootstrap.main()方法中还会为不同目的而创建3个类载入器使用多个类载入器的目的是为了防止应用程序中的类包括servlet类和web 应用程序中的其他辅助类使用 WEB-INF/classes目录 和 WEB-INF/lib 目录之外的类。部署到 %CATALINA_HOME%/common/lib 目录下的那个 JAR 文件的类文件是可以使用的干货——Bootstrap.main()方法中还会为不同目的而创建3个类载入器 4对3个类载入器进行详细说明4.0三个类载入器的定义如下// Construct the class loaders we will need
ClassLoader commonLoader null;
ClassLoader catalinaLoader null;
ClassLoader sharedLoader null;Attention对于每个类载入器都会指定一条可以访问的路径4.1commonLoader类载入器可以载入 %CATALINA_HOME%/common/classes 目录 %CATALINA_HOME%/common/endorsed 目录 和 %CATALINA_HOME%/common/lib 目录下的java类try {File unpacked[] new File[1];File packed[] new File[1];File packed2[] new File[2];ClassLoaderFactory.setDebug(debug);unpacked[0] new File(getCatalinaHome(),common File.separator classes);packed2[0] new File(getCatalinaHome(),common File.separator endorsed);packed2[1] new File(getCatalinaHome(),common File.separator lib);commonLoader ClassLoaderFactory.createClassLoader(unpacked, packed2, null);4.2catalinaLoader类加载器负责载入运行 Catalina servlet 容器所需要的类。它可以载入 %CATALINA_HOME%/server/classes 目录 %CATALINA_HOME%/server/lib 目录 以及commonLoader 类载入器可以访问的所有目录中的java类unpacked[0] new File(getCatalinaHome(),server File.separator classes);packed[0] new File(getCatalinaHome(),server File.separator lib);catalinaLoader ClassLoaderFactory.createClassLoader(unpacked, packed,commonLoader);4.3sharedLoader类可以载入 %CATALINA_HOME%/shared/classes 目录 和 %CATALINA_HOME%/share/lib 目录以及commonLoader 类载入器可以访问的所有目录中的java类unpacked[0] new File(getCatalinaBase(),shared File.separator classes);packed[0] new File(getCatalinaBase(),shared File.separator lib);sharedLoader ClassLoaderFactory.createClassLoader(unpacked, packed,commonLoader);} catch (Throwable t) {log(Class loader creation threw exception, t);System.exit(1);}public static ClassLoader createClassLoader(File unpacked[],File packed[],ClassLoader parent)throws Exception { //org.apache.catalina.startup.ClassLoaderFactory.createClassLoader().if (debug 1)log(Creating new class loader);// Construct the class path for this class loaderArrayList list new ArrayList();// Add unpacked directoriesif (unpacked ! null) {for (int i 0; i unpacked.length; i) {File file unpacked[i];if (!file.isDirectory() || !file.exists() || !file.canRead())continue;if (debug 1)log( Including directory file.getAbsolutePath());URL url new URL(file, null,file.getCanonicalPath() File.separator);list.add(url.toString());}}// Add packed directory JAR filesif (packed ! null) {for (int i 0; i packed.length; i) {File directory packed[i];if (!directory.isDirectory() || !directory.exists() ||!directory.canRead())continue;String filenames[] directory.list();for (int j 0; j filenames.length; j) {String filename filenames[j].toLowerCase();if (!filename.endsWith(.jar))continue;File file new File(directory, filenames[j]);if (debug 1)log( Including jar file file.getAbsolutePath());URL url new URL(file, null,file.getCanonicalPath());list.add(url.toString());}}}// Construct the class loader itselfString array[] (String[]) list.toArray(new String[list.size()]);StandardClassLoader classLoader null;if (parent null)classLoader new StandardClassLoader(array);elseclassLoader new StandardClassLoader(array, parent);classLoader.setDelegate(true);return (classLoader);} AttentionA1在tomcat中每个 web 应用程序中与 Context容器相关联的每个类载入器的父类载入器都是sharedLoader 类载入器 A2sharedLoader类载入器并不能访问 Catalina的内部类或 CLASSPATH 环境变量指定的类路径中的类 5在创建了3个类载入器之后main(方法会载入Catalina类并创建它的一个实例然后再将其赋值给 startupInstance 变量Class startupClass catalinaLoader.loadClass(org.apache.catalina.startup.Catalina);Object startupInstance startupClass.newInstance();6然后它调用setParentClassLoader()方法并将 sharedLoader类载入器作为参数传入// Set the shared extensions class loaderif (debug 1)log(Setting startup class properties);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);7最后main()方法会调用 Catalina.process()方法for spec info of Catalina.process(), please refer to the supplement of chapter [1]// Call the process() methodif (debug 1)log(Calling startup class process() method);methodName process;paramTypes new Class[1];paramTypes[0] args.getClass();paramValues new Object[1];paramValues[0] args;method startupInstance.getClass().getMethod(methodName, paramTypes);method.invoke(startupInstance, paramValues);【3】在Windows 平台上运行tomcat1可以调用 startup.bat或shutdown.bat 批处理文件来 启动或关闭 tomcat【3.1】如何编写批处理文件AttentionA1首先批处理文件的后缀名必须是 “.bat” A2DOS 目录及环境变量是区分大小写的 0对批处理命令进行introcommandsc1rem 该命令用于注释。解释器将不会执行以rem 命令开始的行 c2pause该命令用于暂停正在执行的批处理文件并提示用户按某个键然后程序会继续运行 c3echo该命令用于在dos 控制台上显示一段文本。例如下面的命令将在控制台上输出“hello world”然后暂停程序。之所以暂停程序是为了能够使控制台将输出的文本显示出来 echo hello world
pause c3.1如果想要显示环境变量的值需要在其的前后添加 %%如下面的目录将输出变量myVar的值 echo %myVar% c3.2如果想要输出操作系统的名字可以使用如下的命令 echo %OS% c4echo off使用echo off 命令可以防止将批处理文件中的具体命令输出而只会输出执行结果。但是“echo off”命令本身还是会显示出来。如果想要将 “echo off”也隐藏起来需要使用 echo off 命令 c5echo off该命令与 echo off 命令类似但是他会连 echo off 命令也隐藏起来 c6set用来设置用户定义或命名的环境变量。在批处理文件中设置的环境变量是临时存储在内存中的在批处理文件执行完成后就会销毁 看个荔枝下面的set命令创建了一个名为 “usernmae”的环境变量其值为“tang”并输出到consoleset usernametang
echo %username%
pause Attention为了获取变量的值需要在变量前后添加“%”符号。如 “echo %username%”在字符串中就可以取到 username的值c7label使用冒号设置一个标签。然后可以将标签传递给goto命令这样程序就会跳转到标签指定的位置。下面的语句定义了一个end的标签:end c8gotogoto命令强制批处理文件跳转到指定标签所在的位置继续执行 看个荔枝echo start
goto end
echo i am a student;
:end
echo end
pause对以上脚本的分析Analysis在第1行输出start后批处理文件会执行 goto命令跳转到end标签处c9ifif用来测试条件测试有3种用法func干货——if命令用来测试条件测试有3种用法 if variablevalue nextCommand func1测试变量的值 set myVar3 if %myVar%3 echo Correct func2测试文件是否存在 if exist c:\temp\myFile.txt goto start func3测试错误值 set myVar3 if not %myVar%3 echo Correct c10notnot关键字用来对一条语句取反 c11exist当测试文件是否存在时会使用到 if 和 exist命令 c12接收参数可以给批处理文件传递参数并使用%1 引用第1个参数%2 引用第2个参数以此类推 c12.1echo %1将在console 输出 第1个参数的值如果批处理文件的名字是 test.bat并使用 “test hello” 命令来调用它那么将会在console中输出 “hello” 看个荔枝下面的文件会对第1个参数进行检查。如果是start输出“start”如果是stop输出stop否则输出invalidecho off
if %1start goto start
if %1stop goto stop
go invalid
:start
echo start
go end
:stop
echo stop
goto end
:invalid
echo invalide
:endAttention若要检查运行批处理文件时是否带有参数可以将 %1 与 空字符串进行比较。如对于下面的批处理文件如果运行时没有使用参数就会在控制台上输出“no parameter”if %1 echo no parameter
orif %1 echo no parameterc13shiftshift命令用来将参数向后移动一位即将%2的值复制给%1%3的值复制给%2以此类推例如下面的代码使用一条shift命令 echo off
shift
echo %1
echo %2 如果在运行批处理文件时附加了3个参数ab和c那么上面的命令会有如下输出
b
c
移动之后要使用 %0 来应用第1个参数而现在最后一个参数已经失效了 c14call该命令用来调用另一条命令 c15setLocal在批处理文件中使用 setLocal对环境变量的修改只在当前批处理脚本中有效。当遇到endLocal 命令后在批处理文件的末尾修改的环境变量的值会恢复成原来的值 c16start打开一个新的Windows控制台并可以为这个新的控制台指定一个名字如 start title 此外在 title后面还有传入一条将要在新的控制台中执行的目录如下所示 start title commandName 【3.2】 catalina.bat 批处理文件1catalina.bat 批处理文件用来启动或关闭tomcat。另外两个文件startup.bat 和 shutdown.bat提供了更简单地启动和关闭tomcat的方法。实际上startup.bat 和 shutdown.bat 都会调用catalina.bar 文件并传入相应的参数2在%CATALINA_HOME%/bin 目录下需要以下面的语法格式调用 catalina.bar 脚本catalina 或会使用下面的语法 从 %CATALINA_HOME%/bin 目录下调用该脚本 bin\catalina3在两种case下参数command 的可选值包括c1debug在调试器中启动 Catalina c2debug -security在使用安全管理器的case下调试 Catalina c3embedded以嵌入模式启动Catalina c4jpda start在 JPDA调试器下启动 Catalina c5run在当前窗口中启动 Catalina r6run -security在当前窗口中通过安全管理器启动 Catalina r7start在新窗口中启动 Catalina r8start -security在新窗口中通过安全管理器启动 Catalina r9stop关闭Catalina 看个荔枝想在新窗口中启动 Catalina可以使用如下命令catalina start4catalina.bat 批处理文件的内容 https://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/catalina.bat对catalina.bat 文件的分析Analysis暂时省略Supplement Supplement1catalina.bat 文件中通过设置MAINCLASSorg.apache.catalina.startup.Bootstrap然后在该bat文件末尾会运行该类Bootstrap set MAINCLASSorg.apache.catalina.startup.Bootstrap // line 203rem Execute Java with the applicable properties //line 307.
if not %JPDA% goto doJpda
if not %SECURITY_POLICY_FILE% goto doSecurity
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs%JAVA_ENDORSED_DIRS% -classpath %CLASSPATH% -Dcatalina.base%CATALINA_BASE% -Dcatalina.home%CATALINA_HOME% -Djava.io.tmpdir%CATALINA_TMPDIR% %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doSecurity
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs%JAVA_ENDORSED_DIRS% -classpath %CLASSPATH% -Djava.security.manager -Djava.security.policy%SECURITY_POLICY_FILE% -Dcatalina.base%CATALINA_BASE% -Dcatalina.home%CATALINA_HOME% -Djava.io.tmpdir%CATALINA_TMPDIR% %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doJpda
if not %SECURITY_POLICY_FILE% goto doSecurityJpda
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs%JAVA_ENDORSED_DIRS% -classpath %CLASSPATH% -Dcatalina.base%CATALINA_BASE% -Dcatalina.home%CATALINA_HOME% -Djava.io.tmpdir%CATALINA_TMPDIR% %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end
:doSecurityJpda
%_EXECJAVA% %JAVA_OPTS% %CATALINA_OPTS% %JPDA_OPTS% %DEBUG_OPTS% -Djava.endorsed.dirs%JAVA_ENDORSED_DIRS% -classpath %CLASSPATH% -Djava.security.manager -Djava.security.policy%SECURITY_POLICY_FILE% -Dcatalina.base%CATALINA_BASE% -Dcatalina.home%CATALINA_HOME% -Djava.io.tmpdir%CATALINA_TMPDIR% %MAINCLASS% %CMD_LINE_ARGS% %ACTION%
goto end // line 321Supplement2 总结tomcat启动steps不能再干货step1startup.bat 批处理文件会调用 catalina.bat 文件而catalina.bat批处理会运行org.apache.catalina.startup.Bootstrap 类main方法 step2Bootstrap.main()方法会调用 Catalina.process()方法 public final class Bootstrap { //org.apache.catalina.startup.Bootstrapprivate static int debug 0; public static void main(String args[]) {// Set the debug flag appropriatelyfor (int i 0; i args.length; i) {if (-debug.equals(args[i]))debug 1;}// Configure catalina.base from catalina.home if not yet setif (System.getProperty(catalina.base) null)System.setProperty(catalina.base, getCatalinaHome());// Construct the class loaders we will needClassLoader commonLoader null;ClassLoader catalinaLoader null;ClassLoader sharedLoader null;try {File unpacked[] new File[1];File packed[] new File[1];File packed2[] new File[2];ClassLoaderFactory.setDebug(debug);unpacked[0] new File(getCatalinaHome(),common File.separator classes);packed2[0] new File(getCatalinaHome(),common File.separator endorsed);packed2[1] new File(getCatalinaHome(),common File.separator lib);commonLoader ClassLoaderFactory.createClassLoader(unpacked, packed2, null);unpacked[0] new File(getCatalinaHome(),server File.separator classes);packed[0] new File(getCatalinaHome(),server File.separator lib);catalinaLoader ClassLoaderFactory.createClassLoader(unpacked, packed,commonLoader);unpacked[0] new File(getCatalinaBase(),shared File.separator classes);packed[0] new File(getCatalinaBase(),shared File.separator lib);sharedLoader ClassLoaderFactory.createClassLoader(unpacked, packed,commonLoader);} catch (Throwable t) {log(Class loader creation threw exception, t);System.exit(1);}Thread.currentThread().setContextClassLoader(catalinaLoader);// Load our startup class and call its process() methodtry {SecurityClassLoad.securityClassLoad(catalinaLoader);// Instantiate a startup class instanceif (debug 1)log(Loading startup class);Class startupClass catalinaLoader.loadClass(org.apache.catalina.startup.Catalina); //highlight line.Object startupInstance startupClass.newInstance(); // 创建Catalina类的实例.// Set the shared extensions class loaderif (debug 1)log(Setting startup class properties);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);// Call the process() method //highlight line.if (debug 1)log(Calling startup class process() method);methodName process; //highlight line.paramTypes new Class[1];paramTypes[0] args.getClass();paramValues new Object[1];paramValues[0] args;method startupInstance.getClass().getMethod(methodName, paramTypes); // 调用Catalina.process()方法.method.invoke(startupInstance, paramValues);} catch (Exception e) {System.out.println(Exception during startup processing);e.printStackTrace(System.out);System.exit(2);}} private static String getCatalinaHome() {return System.getProperty(catalina.home,System.getProperty(user.dir));} private static String getCatalinaBase() {return System.getProperty(catalina.base, getCatalinaHome());} private static void log(String message) {System.out.print(Bootstrap: );System.out.println(message);} private static void log(String message, Throwable exception) {log(message);exception.printStackTrace(System.out);}
}Attention文末会对createStateDigester()方法的调用过程进一步总结限于篇幅?xml version1.0 encodingutf-8? !--conf/server.xml源码如下 --
!--Licensed to the Apache Software Foundation (ASF) under one or morecontributor license agreements. See the NOTICE file distributed withthis work for additional information regarding copyright ownership.The ASF licenses this file to You under the Apache License, Version 2.0(the License); you may not use this file except in compliance withthe License. You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an AS IS BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.
--
!-- Note: A Server is not itself a Container, so you may notdefine subcomponents such as Valves at this level.Documentation at /docs/config/server.html--
Server port8005 shutdownSHUTDOWN!-- Security listener. Documentation at /docs/config/listeners.htmlListener classNameorg.apache.catalina.security.SecurityListener /--!--APR library loader. Documentation at /docs/apr.html --Listener classNameorg.apache.catalina.core.AprLifecycleListener SSLEngineon /!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --Listener classNameorg.apache.catalina.core.JasperListener /!-- Prevent memory leaks due to use of particular java/javax APIs--Listener classNameorg.apache.catalina.core.JreMemoryLeakPreventionListener /Listener classNameorg.apache.catalina.mbeans.GlobalResourcesLifecycleListener /Listener classNameorg.apache.catalina.core.ThreadLocalLeakPreventionListener /!-- Global JNDI resourcesDocumentation at /docs/jndi-resources-howto.html--GlobalNamingResources!-- Editable user database that can also be used byUserDatabaseRealm to authenticate users--Resource nameUserDatabase authContainertypeorg.apache.catalina.UserDatabasedescriptionUser database that can be updated and savedfactoryorg.apache.catalina.users.MemoryUserDatabaseFactorypathnameconf/tomcat-users.xml //GlobalNamingResources!-- A Service is a collection of one or more Connectors that sharea single Container Note: A Service is not itself a Container,so you may not define subcomponents such as Valves at this level.Documentation at /docs/config/service.html--Service nameCatalina!--The connectors can use a shared executor, you can define one or more named thread pools--!--Executor nametomcatThreadPool namePrefixcatalina-exec-maxThreads150 minSpareThreads4/--!-- A Connector represents an endpoint by which requests are receivedand responses are returned. Documentation at :Java HTTP Connector: /docs/config/http.html (blocking non-blocking)Java AJP Connector: /docs/config/ajp.htmlAPR (HTTP/AJP) Connector: /docs/apr.htmlDefine a non-SSL HTTP/1.1 Connector on port 8080--Connector port8888 protocolHTTP/1.1connectionTimeout20000redirectPort8443 /!-- A Connector using the shared thread pool--!--Connector executortomcatThreadPoolport8080 protocolHTTP/1.1connectionTimeout20000redirectPort8443 /--!-- Define a SSL HTTP/1.1 Connector on port 8443This connector uses the JSSE configuration, when using APR, theconnector should be using the OpenSSL style configurationdescribed in the APR documentation --!--Connector port8443 protocolHTTP/1.1 SSLEnabledtruemaxThreads150 schemehttps securetrueclientAuthfalse sslProtocolTLS /--!-- Define an AJP 1.3 Connector on port 8009 --Connector port8009 protocolAJP/1.3 redirectPort8443 /!-- An Engine represents the entry point (within Catalina) that processesevery request. The Engine implementation for Tomcat stand aloneanalyzes the HTTP headers included with the request, and passes themon to the appropriate Host (virtual host).Documentation at /docs/config/engine.html --!-- You should set jvmRoute to support load-balancing via AJP ie :Engine nameCatalina defaultHostlocalhost jvmRoutejvm1--Engine nameCatalina defaultHostlocalhost!--For clustering, please take a look at documentation at:/docs/cluster-howto.html (simple how to)/docs/config/cluster.html (reference documentation) --!--Cluster classNameorg.apache.catalina.ha.tcp.SimpleTcpCluster/--!-- Use the LockOutRealm to prevent attempts to guess user passwordsvia a brute-force attack --Realm classNameorg.apache.catalina.realm.LockOutRealm!-- This Realm uses the UserDatabase configured in the global JNDIresources under the key UserDatabase. Any editsthat are performed against this UserDatabase are immediatelyavailable for use by the Realm. --Realm classNameorg.apache.catalina.realm.UserDatabaseRealmresourceNameUserDatabase//RealmHost namelocalhost appBasewebappsunpackWARstrue autoDeploytrue!-- SingleSignOn valve, share authentication between web applicationsDocumentation at: /docs/config/valve.html --!--Valve classNameorg.apache.catalina.authenticator.SingleSignOn /--!-- Access log processes all example.Documentation at: /docs/config/valve.htmlNote: The pattern used is equivalent to using patterncommon --Valve classNameorg.apache.catalina.valves.AccessLogValve directorylogsprefixlocalhost_access_log. suffix.txtpattern%h %l %u %t %r %s %b //Host/Engine/Service
/Server
对以上server.xml代码的分析AnalysisA1创建一个服务器组件A1.1服务器组件里面注入多个监听器资源GlobalNamingResources A1.2创建一个服务组件 A1.2.1创建两个Connector A1.2.2创建一个EngineEngine中注入两个领域对象Realm还注入了一个Host容器和一个阀 AttentionA1服务器组件和服务组件参见 tomcat(14)服务器组件和服务组件 A2Digester用于将XML 文档中的元素转换成 java 对象参见 tomcat(15)Digester库 Conclusion不能再干货——tomcat的启动调用过程review C1自此tomcat的启动调用过程我们已经分析完毕再review 一下 startup.bat - catalina.bat - Bootstrap.main() - Catalina.process() - createStartDigester() -configFile() C2启动createStartDigester方法会创建Digester类用于将server.xml 中的元素转换为java对象而configFile方法就是用于设定 将要解析的xml的文件路径的. 【3.3】在Windows 平台上启动tomcatstartup.bat 文件调用catalina.bat 文件时会传入参数 starthttps://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/startup.bat 【3.4】在Windows 平台上关闭tomcatshutdown.bat 文件调用 catalina.bat文件时传入参数 stophttps://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/shutdown.bat 【4】在Linux平台上启动Tomcat1在linux平台上tomcat使用shell 脚本来启动和关闭。shell脚本的后缀名可以是 “.sh”位于 $CATALINA_HOME/bin 目录下2intro本章节将intro 4 个脚本catalina.sh, statup.sh, shutdown.sh, setclasspath.sh【4.1】如何编写UNIX/Linux Shell脚本1introshell脚本是由解释器逐行执行的shell 脚本的扩展名可有可无但最常用的扩展名是 .sh2下面简单介绍下 shell 命令(command)c1注释shell脚本使用 # 符号来表示注释内容 c2clear使用该命令来清空屏幕 c3exit该命令可以用来退出当前shell 脚本的执行一般case下exit后面都会附加一个退出状态其中0 表示shell脚本正常执行完成非0值表示shell异常退出如果因为程序运行中的某种异常而想退出使用如下命令exit 1干货——exit后面都会附加一个退出状态其中0 表示shell脚本正常执行完成非0值表示shell异常退出 c4echo该命令可以向屏幕输出一个字符串echo hello world c5调用函数可以使用句点(.)来调用一个函数或执行另一个shell 脚本 c6系统变量与用于自定义变量变量名必须以字母数字或下划线开头使用等号就可以定义一个变量如下面的命令定义了一个名为 myVar 的变量其值为 TootsiemyVarToosie AttentionA1等号的前后一定不能有空格。此外shell 脚本对变量名是区分大小写的 A2若想定义一个值为NULL的变量可使用空字符串为其赋值或在等号右边留空即可 myVar
myVar A3若想要获取变量的值需要在变量前面加上美元符号$echo $myVar A4Unix/Linux 提供了一些系统变量供用户使用如变量HOME 保存了当前用户的主目录变量PWD 保存了用户当前所在的目录变量PATH 保存了将会在哪些地方查找要执行的命令等 c7expr 可以使用该命令来计算一个表达式的值。表达式必须以反引号引用如下面的shell 脚本计算一个数学表达式 sumexpr 100200
echo $sum c7.1脚本:echo expr 200300 会输出500 c7.2特殊表达式uname会得到操作系统的名称echo uname 会输出操作系统名称Linux或Unix c7.3特殊表达式 dirname filePath 会返回指定文件所在的目录。如命令 dirname /home/user1/test.sh 会返回“home/user1” c8访问参数如同向函数中传入参数一样也可以向shell脚本传入参数并使用 $1 来引用第1个参数$2引用第2个参数以此类推$# 会返回参数的格式$会返回所有的参数 c9shift这条命令会将参数向后移动一位$1的值改为 $2 $2的值改为$3 以此类推 c10if...then...[else...] fiif 语句用来测试条件并执行相应的命令列表。它的语法格式如下 if condition thenlist of commands
[elselist of commands
]
fi Attention也可以使用 “elif”来代替“else if” 看个荔枝如下面的shell脚本若传入的第1个参数是 “start”运行下面的脚本会输出“start”如果传入的第1个参数是 “stop”则输出“stop”if [ $1 start ]; thenecho start
fi
if [ $1 end ]; thenecho end
fi AttentionA1判断条件在 “[” 后面必须有一个空格 在“]”前面也必须有一个空格 A2将 $1 用双引号引起来可以防止解释器在发现调用脚本时没有使用参数而抛出异常 A3$0表示的是用来调用该脚本的命令。如使用下面的命令来调用一个名为 test.sh 的脚本./test.sh 那么$0 返回 “./test.sh”下面是一些用来进行条件判断的测试选项 -f file当存在文件file时为true
-r file当文件file可读时为true
-z string如果string 是空字符串为 true
-n string如果string 不为空字符串为true
string1 string2如果string1 等于string2为true
string1 ! string2如果string1 不等于 string2为true c11for循环使用for循环来重复执行一些命令 for {var} in {list}
dolist of commands
done 看个荔枝for i in 1 2 3
doecho i$i
done
output
i1
i2
i3 c12while循环 while [condition]
dolist of commands
done 看个荔枝n1
while [$n -lt 3]
doecho i $n
done
output
i1
i2 Attention其中 [$n -lt 3];中 -lt 的意思是小于3lt less than c13casecase结构表示可以在程序中执行一些选择过程。其语法格式如下所示 case $variable-name in
pattern1)list of commands;;
pattern2)list of commands;;
*)list of commands;;
esac Attention“;;”表示命令列表执行完成如果上面的模式都不匹配时“*)”表示所要执行的命令 看个荔枝 case uname inCYGWIN*)echo cygwin;;OS400*)echo os400;;LINUX*)echo linux;;*)echo os not recognized;;
esac c14输出重定向review使用 “”将输出重定向到一个文件echo hello myFile.txt这会创建一个 myFile.txt的文件并将 hello 写入到其中不会向屏幕上输出文字 Supplement S112会把标准输出上的错误消息重定向到标准错误中 S121会把标准错误中的信息重新向到 标准输出中 c15条件执行可以使用命令或条件来决定是否执行另一条命令。在这种 case下 可以使用 或 || 如下所示 c15.1command1 command2如果command1返回的退出状态是0那么会执行command20表true非0表false c15.2command1 || command2如果command1返回的退出状态是非0那么会执行command20表true非0表false c15.3command1 command2 || command3如果command1返回的退出状态是非0那么会执行command2否则执行command30表true非0表false 【4.2】catalina.sh 脚本 1intro 该文件用来在 UNIX/Linux 平台上启动或关闭tomcat。若要启动tomcat需要将 start作为第1个参数传递给 catalina.sh 脚本。若要关闭 tomcat需要将stop 作为第1个参数传递给 catalina.sh脚本。下面是有效的 参数列表parameters: p1debug在调试器中启动catalina在OS400系统上不可用 p2debug -security通过安全管理器调试catalina在OS400系统上不可用 p3embedded以嵌入模式启动 Catalina p4jpda start在JPDA 调试器下启动 Catalina p5run在当前窗口中启动 Catalina p6run -security在安全管理器下使用当前窗口启动 catalina p7start使用一个新窗口启动 catalina p8start -security在安全管理器下使用一个新窗口启动 catalina p9stop关闭 catalina 2catalina.sh 的源代码参见 https://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/catalina.sh 【4.3】在 unix/linux 平台上启动 tomcat 1使用 startup.sh 脚本可以方便地启动 tomcat。startup.sh 脚本会设置正确的环境变量然后调用 catalina.sh脚本并传入参数 start https://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/startup.sh 【4.4】在 unix/linux 平台上关闭 tomcat 1使用 shutdown.sh 脚本可以方便地启动 tomcat。shutdown.sh 脚本会设置正确的环境变量然后调用 catalina.sh脚本并传入参数 stop https://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/shutdown.sh ------------------------------------------------------------------------------------------------------ Supplement文末继续对 Catatalina.createStateDigester()方法的调用过程进一步总结 protected Digester createStartDigester() { //org.apache.catalina.startup.Catalina.createStartDigester().// Initialize the digesterDigester digester new Digester();digester.setClassLoader(StandardServer.class.getClassLoader());if (debug)digester.setDebug(999);digester.setValidating(false);// Configure the actions we will be usingdigester.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 elementclassName);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);digester.addObjectCreate(Server/Service/Listener,null, // MUST be specified in the elementclassName);digester.addSetProperties(Server/Service/Listener);digester.addSetNext(Server/Service/Listener,addLifecycleListener,org.apache.catalina.LifecycleListener);digester.addObjectCreate(Server/Service/Connector,org.apache.catalina.connector.http.HttpConnector,className);digester.addSetProperties(Server/Service/Connector);digester.addSetNext(Server/Service/Connector,addConnector,org.apache.catalina.Connector);digester.addObjectCreate(Server/Service/Connector/Factory,org.apache.catalina.net.DefaultServerSocketFactory,className);digester.addSetProperties(Server/Service/Connector/Factory);digester.addSetNext(Server/Service/Connector/Factory,setFactory,org.apache.catalina.net.ServerSocketFactory);digester.addObjectCreate(Server/Service/Connector/Listener,null, // MUST be specified in the elementclassName);digester.addSetProperties(Server/Service/Connector/Listener);digester.addSetNext(Server/Service/Connector/Listener,addLifecycleListener,org.apache.catalina.LifecycleListener);// Add RuleSets for nested elementsdigester.addRuleSet(new NamingRuleSet(Server/GlobalNamingResources/));digester.addRuleSet(new EngineRuleSet(Server/Service/)); //highlight line.digester.addRuleSet(new HostRuleSet(Server/Service/Engine/)); //highlight line.digester.addRuleSet(new ContextRuleSet(Server/Service/Engine/Default)); //highlight line.digester.addRuleSet(new NamingRuleSet(Server/Service/Engine/DefaultContext/));digester.addRuleSet(new ContextRuleSet(Server/Service/Engine/Host/Default));digester.addRuleSet(new NamingRuleSet(Server/Service/Engine/Host/DefaultContext/));digester.addRuleSet(new ContextRuleSet(Server/Service/Engine/Host/));digester.addRuleSet(new NamingRuleSet(Server/Service/Engine/Host/Context/));digester.addRule(Server/Service/Engine,new SetParentClassLoaderRule(digester,parentClassLoader));return (digester);} public void addRuleInstances(Digester digester) { //org.apache.catalina.startup.EngineRuleSet.addRuleInstances().digester.addObjectCreate(prefix Engine,org.apache.catalina.core.StandardEngine,className);digester.addSetProperties(prefix Engine);digester.addRule(prefix Engine,new LifecycleListenerRule(digester,org.apache.catalina.startup.EngineConfig,engineConfigClass));digester.addSetNext(prefix Engine,setContainer,org.apache.catalina.Container);digester.addObjectCreate(prefix Engine/Listener,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Engine/Listener);digester.addSetNext(prefix Engine/Listener,addLifecycleListener,org.apache.catalina.LifecycleListener);digester.addObjectCreate(prefix Engine/Logger,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Engine/Logger);digester.addSetNext(prefix Engine/Logger,setLogger,org.apache.catalina.Logger);digester.addObjectCreate(prefix Engine/Realm,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Engine/Realm);digester.addSetNext(prefix Engine/Realm,setRealm,org.apache.catalina.Realm);digester.addObjectCreate(prefix Engine/Valve,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Engine/Valve);digester.addSetNext(prefix Engine/Valve,addValve,org.apache.catalina.Valve);}public void addRuleInstances(Digester digester) { //org.apache.catalina.startup.HostRuleSet.addRuleInstances().digester.addObjectCreate(prefix Host,org.apache.catalina.core.StandardHost,className);digester.addSetProperties(prefix Host);digester.addRule(prefix Host,new CopyParentClassLoaderRule(digester));digester.addRule(prefix Host,new LifecycleListenerRule(digester,org.apache.catalina.startup.HostConfig,hostConfigClass));digester.addSetNext(prefix Host,addChild,org.apache.catalina.Container);digester.addCallMethod(prefix Host/Alias,addAlias, 0);digester.addObjectCreate(prefix Host/Cluster,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Host/Cluster);digester.addSetNext(prefix Host/Cluster,addCluster,org.apache.catalina.Cluster);digester.addObjectCreate(prefix Host/Listener,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Host/Listener);digester.addSetNext(prefix Host/Listener,addLifecycleListener,org.apache.catalina.LifecycleListener);digester.addObjectCreate(prefix Host/Logger,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Host/Logger);digester.addSetNext(prefix Host/Logger,setLogger,org.apache.catalina.Logger);digester.addObjectCreate(prefix Host/Realm,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Host/Realm);digester.addSetNext(prefix Host/Realm,setRealm,org.apache.catalina.Realm);digester.addObjectCreate(prefix Host/Valve,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Host/Valve);digester.addSetNext(prefix Host/Valve,addValve,org.apache.catalina.Valve);}public void addRuleInstances(Digester digester) { //span stylefont-family:Arial, Helvetica, sans-serif; org.apache.catalina.ContextRuleSet.addRuleInstances()./span
if (!isDefaultContext()) {digester.addObjectCreate(prefix Context,org.apache.catalina.core.StandardContext,className);} else {digester.addObjectCreate(prefix Context,org.apache.catalina.core.StandardDefaultContext,className);}digester.addSetProperties(prefix Context);if (!isDefaultContext()) {digester.addRule(prefix Context,new CopyParentClassLoaderRule(digester));digester.addRule(prefix Context,new LifecycleListenerRule(digester,org.apache.catalina.startup.ContextConfig,configClass));digester.addSetNext(prefix Context,addChild,org.apache.catalina.Container);digester.addRule(prefix Context,new ContextValidatorRule(digester));} else {digester.addSetNext(prefix Context,addDefaultContext,org.apache.catalina.DefaultContext);}digester.addCallMethod(prefix Context/InstanceListener,addInstanceListener, 0);digester.addObjectCreate(prefix Context/Listener,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Context/Listener);digester.addSetNext(prefix Context/Listener,addLifecycleListener,org.apache.catalina.LifecycleListener);digester.addRule(prefix Context/Loader,new CreateLoaderRule(digester,org.apache.catalina.loader.WebappLoader,className));digester.addSetProperties(prefix Context/Loader);digester.addSetNext(prefix Context/Loader,setLoader,org.apache.catalina.Loader);digester.addObjectCreate(prefix Context/Logger,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Context/Logger);digester.addSetNext(prefix Context/Logger,setLogger,org.apache.catalina.Logger);digester.addObjectCreate(prefix Context/Manager,org.apache.catalina.session.StandardManager,className);digester.addSetProperties(prefix Context/Manager);digester.addSetNext(prefix Context/Manager,setManager,org.apache.catalina.Manager);digester.addObjectCreate(prefix Context/Manager/Store,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Context/Manager/Store);digester.addSetNext(prefix Context/Manager/Store,setStore,org.apache.catalina.Store);digester.addObjectCreate(prefix Context/Parameter,org.apache.catalina.deploy.ApplicationParameter);digester.addSetProperties(prefix Context/Parameter);digester.addSetNext(prefix Context/Parameter,addApplicationParameter,org.apache.catalina.deploy.ApplicationParameter);digester.addObjectCreate(prefix Context/Realm,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Context/Realm);digester.addSetNext(prefix Context/Realm,setRealm,org.apache.catalina.Realm);digester.addObjectCreate(prefix Context/ResourceLink,org.apache.catalina.deploy.ContextResourceLink);digester.addSetProperties(prefix Context/ResourceLink);digester.addSetNext(prefix Context/ResourceLink,addResourceLink,org.apache.catalina.deploy.ContextResourceLink);digester.addObjectCreate(prefix Context/Resources,org.apache.naming.resources.FileDirContext,className);digester.addSetProperties(prefix Context/Resources);digester.addSetNext(prefix Context/Resources,setResources,javax.naming.directory.DirContext);digester.addObjectCreate(prefix Context/Valve,null, // MUST be specified in the elementclassName);digester.addSetProperties(prefix Context/Valve);digester.addSetNext(prefix Context/Valve,addValve,org.apache.catalina.Valve);digester.addCallMethod(prefix Context/WrapperLifecycle,addWrapperLifecycle, 0);digester.addCallMethod(prefix Context/WrapperListener,addWrapperListener, 0);} 对以上代码的分析Analysis A1EngineRuleSet.addRuleInstances方法创建Engine容器StandardEngineEngine监听器EngineConfig 声明周期监听器 LifecycleListener 日志Logger 领域对象Realm 管道阀对象 Valve A2HostRuleSet.addRuleInstances方法创建Host容器StandardHost Host监听器HostConfig 集群Cluster 生命周期监听器LifecycleListener 日志Logger 领域对象Realm 管道阀对象 Valve A3ContextRuleSet.addRuleInstances方法创建Context容器 StandardContext Context监听器ContextConfig 生命周期监听器LifecycleListenerWeb加载器WebappLoader 管理器Manager Store 领域对象Realm ContextResourceLink 管道阀对象Valve