查看tomcat启动文件都干点啥---Catalina.java
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了查看tomcat启动文件都干点啥---Catalina.java,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含14848字,纯文字阅读大概需要22分钟。
内容图文
![查看tomcat启动文件都干点啥---Catalina.java](/upload/InfoBanner/zyjiaocheng/1070/5a2ee2d92c3e4231aa697c3dcb0adf23.jpg)
在前一章查看tomcat启动文件都干点啥---Bootstrap.java中我们得出结论,在Bootstrap中通过反射调用Catalina类中的getServer,start,stop,stopServer等方法,下面看一下Catalina类中给外部提供的公共方法:
Start:其中Catalina类的入口当然是start方法.start方法实现了启动一个新的server事例的功能,看一下start方法的内容:
1 public void start() { 2 3 if (getServer() == null) { 4 load(); 5 } 6 7if (getServer() == null) { 8 log.fatal("Cannot start server. Server instance is not configured."); 9return; 10 } 1112long t1 = System.nanoTime(); 1314// Start the new server15try { 16 getServer().start(); 17 } catch (LifecycleException e) { 18 log.fatal(sm.getString("catalina.serverStartFail"), e); 19try { 20 getServer().destroy(); 21 } catch (LifecycleException e1) { 22 log.debug("destroy() failed for failed Server ", e1); 23 } 24return; 25 } 2627long t2 = System.nanoTime(); 28if(log.isInfoEnabled()) { 29 log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms"); 30 } 3132// Register shutdown hook33if (useShutdownHook) { 34if (shutdownHook == null) { 35 shutdownHook = new CatalinaShutdownHook(); 36 } 37 Runtime.getRuntime().addShutdownHook(shutdownHook); 3839// If JULI is being used, disable JULI‘s shutdown hook since 40// shutdown hooks run in parallel and log messages may be lost 41// if JULI‘s hook completes before the CatalinaShutdownHook()42 LogManager logManager = LogManager.getLogManager(); 43if (logManager instanceof ClassLoaderLogManager) { 44 ((ClassLoaderLogManager) logManager).setUseShutdownHook( 45false); 46 } 47 } 4849if (await) { 50 await(); 51 stop(); 52 } 53 }
在Catalina中有个很重要的对象就是Server,先说明一下,在tomcat中实现Server接口的StandardServer对象,其中定义了socketServer,在此只作此说明,不展开介绍,在下一章中会专门对StandardServer类以及Server接口进行说明。
在start方法中首先需要判断是否初始化了实现server接口的类(以后都称作server类,不要误解Server为一个类),如果没有的话,那么调用load方法。
load方法中调用了一下几个方法:
initDirs:将Bootstrap中定义的catalina.home的值赋给CATALINA_BASE_PROP属性。以及对java.io.tmpdir属性的验证,下面是initDirs的代码实现:
1 protected void initDirs() { 2 3 String catalinaHome = System.getProperty(Globals.CATALINA_HOME_PROP); 4if (catalinaHome == null) { 5// Backwards compatibility patch for J2EE RI 1.3 6 String j2eeHome = System.getProperty("com.sun.enterprise.home"); 7if (j2eeHome != null) { 8 catalinaHome=System.getProperty("com.sun.enterprise.home"); 9 } elseif (System.getProperty(Globals.CATALINA_BASE_PROP) != null) { 10 catalinaHome = System.getProperty(Globals.CATALINA_BASE_PROP); 11 } 12 } 13// last resort - for minimal/embedded cases.14if(catalinaHome==null) { 15 catalinaHome=System.getProperty("user.dir"); 16 } 17if (catalinaHome != null) { 18 File home = new File(catalinaHome); 19if (!home.isAbsolute()) { 20try { 21 catalinaHome = home.getCanonicalPath(); 22 } catch (IOException e) { 23 catalinaHome = home.getAbsolutePath(); 24 } 25 } 26 System.setProperty(Globals.CATALINA_HOME_PROP, catalinaHome); 27 } 2829if (System.getProperty(Globals.CATALINA_BASE_PROP) == null) { 30 System.setProperty(Globals.CATALINA_BASE_PROP, 31 catalinaHome); 32 } else { 33 String catalinaBase = System.getProperty(Globals.CATALINA_BASE_PROP); 34 File base = new File(catalinaBase); 35if (!base.isAbsolute()) { 36try { 37 catalinaBase = base.getCanonicalPath(); 38 } catch (IOException e) { 39 catalinaBase = base.getAbsolutePath(); 40 } 41 } 42 System.setProperty(Globals.CATALINA_BASE_PROP, catalinaBase); 43 } 4445 String temp = System.getProperty("java.io.tmpdir"); 46if (temp == null || (!(new File(temp)).exists()) 47 || (!(new File(temp)).isDirectory())) { 48 log.error(sm.getString("embedded.notmp", temp)); 49 } 5051 }
其中首先是兼容J2EE RI 1.3,获取com.sun.enterprise.home属性的值赋值给catalinaHome,如果不存在com.sun.enterprise.home这个属性,将Bootstrap中定义的catalina.home的值赋给CATALINA_BASE_PROP属性,如果以上都不成立,那么就是获取当前目录赋给CATALINA_BASE_PROP属性。其实当前目录也就是将Bootstrap中定义的catalina.home的值。只是在tomcat中进行了很繁琐的验证,当然这是有必要的。
createStartDigester:用来生成server.xml的操作,下面是代码实现:
1 protected Digester createStartDigester() { 2 long t1=System.currentTimeMillis(); 3// Initialize the digester 4 Digester digester = new Digester(); 5 digester.setValidating(false); 6 digester.setRulesValidation(true); 7 HashMap<Class<?>, List<String>> fakeAttributes = 8new HashMap<Class<?>, List<String>>(); 9 ArrayList<String> attrs = new ArrayList<String>(); 10 attrs.add("className"); 11 fakeAttributes.put(Object.class, attrs); 12 digester.setFakeAttributes(fakeAttributes); 13 digester.setUseContextClassLoader(true); 14 15// Configure the actions we will be using 16 digester.addObjectCreate("Server", 17 "org.apache.catalina.core.StandardServer", 18 "className"); 19 digester.addSetProperties("Server"); 20 digester.addSetNext("Server", 21 "setServer", 22 "org.apache.catalina.Server"); 23 24 digester.addObjectCreate("Server/GlobalNamingResources", 25 "org.apache.catalina.deploy.NamingResources"); 26 digester.addSetProperties("Server/GlobalNamingResources"); 27 digester.addSetNext("Server/GlobalNamingResources", 28 "setGlobalNamingResources", 29 "org.apache.catalina.deploy.NamingResources"); 30 31 digester.addObjectCreate("Server/Listener", 32null, // MUST be specified in the element 33 "className"); 34 digester.addSetProperties("Server/Listener"); 35 digester.addSetNext("Server/Listener", 36 "addLifecycleListener", 37 "org.apache.catalina.LifecycleListener"); 38 39 digester.addObjectCreate("Server/Service", 40 "org.apache.catalina.core.StandardService", 41 "className"); 42 digester.addSetProperties("Server/Service"); 43 digester.addSetNext("Server/Service", 44 "addService", 45 "org.apache.catalina.Service"); 46 47 digester.addObjectCreate("Server/Service/Listener", 48null, // MUST be specified in the element 49 "className"); 50 digester.addSetProperties("Server/Service/Listener"); 51 digester.addSetNext("Server/Service/Listener", 52 "addLifecycleListener", 53 "org.apache.catalina.LifecycleListener"); 54 55//Executor 56 digester.addObjectCreate("Server/Service/Executor", 57 "org.apache.catalina.core.StandardThreadExecutor", 58 "className"); 59 digester.addSetProperties("Server/Service/Executor"); 60 61 digester.addSetNext("Server/Service/Executor", 62 "addExecutor", 63 "org.apache.catalina.Executor"); 64 65 66 digester.addRule("Server/Service/Connector", 67new ConnectorCreateRule()); 68 digester.addRule("Server/Service/Connector", 69new SetAllPropertiesRule(new String[]{"executor"})); 70 digester.addSetNext("Server/Service/Connector", 71 "addConnector", 72 "org.apache.catalina.connector.Connector"); 73 74 75 digester.addObjectCreate("Server/Service/Connector/Listener", 76null, // MUST be specified in the element 77 "className"); 78 digester.addSetProperties("Server/Service/Connector/Listener"); 79 digester.addSetNext("Server/Service/Connector/Listener", 80 "addLifecycleListener", 81 "org.apache.catalina.LifecycleListener"); 82 83// Add RuleSets for nested elements 84 digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/")); 85 digester.addRuleSet(new EngineRuleSet("Server/Service/")); 86 digester.addRuleSet(new HostRuleSet("Server/Service/Engine/")); 87 digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/")); 88 addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/"); 89 digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/")); 90 91// When the ‘engine‘ is found, set the parentClassLoader. 92 digester.addRule("Server/Service/Engine", 93new SetParentClassLoaderRule(parentClassLoader)); 94 addClusterRuleSet(digester, "Server/Service/Engine/Cluster/"); 95 96long t2=System.currentTimeMillis(); 97if (log.isDebugEnabled()) { 98 log.debug("Digester for server.xml created " + ( t2-t1 )); 99 } 100return (digester); 101102 }
在具体说明之前,我觉得有必要对Digester进行一下说明,以为可能有很多人和我一样,目前为止还还不是很清楚Digester为什么东西,其实他就是一个XML解析器,在这里就是构造一下tomcat启动时候的各种参数,各种初始化方法,初始化server,listener,connector,Executor等数据,我觉得这里有很多内容可以展开来说,所以我打算把他放到下一个章节专门对tomcat中Digester进行说明。在这里特别需要注意的就是如下这部分内容:
1 digester.addObjectCreate("Server", 2 "org.apache.catalina.core.StandardServer", 3 "className"); 4 digester.addSetProperties("Server"); 5 digester.addSetNext("Server", 6 "setServer", 7 "org.apache.catalina.Server"); 8 9 digester.addObjectCreate("Server/GlobalNamingResources", 10 "org.apache.catalina.deploy.NamingResources"); 11 digester.addSetProperties("Server/GlobalNamingResources"); 12 digester.addSetNext("Server/GlobalNamingResources", 13 "setGlobalNamingResources", 14 "org.apache.catalina.deploy.NamingResources"); 1516 digester.addObjectCreate("Server/Listener", 17null, // MUST be specified in the element18 "className"); 19 digester.addSetProperties("Server/Listener"); 20 digester.addSetNext("Server/Listener", 21 "addLifecycleListener", 22 "org.apache.catalina.LifecycleListener"); 2324 digester.addObjectCreate("Server/Service", 25 "org.apache.catalina.core.StandardService", 26 "className"); 27 digester.addSetProperties("Server/Service"); 28 digester.addSetNext("Server/Service", 29 "addService", 30 "org.apache.catalina.Service"); 3132 digester.addObjectCreate("Server/Service/Listener", 33null, // MUST be specified in the element34 "className"); 35 digester.addSetProperties("Server/Service/Listener"); 36 digester.addSetNext("Server/Service/Listener", 37 "addLifecycleListener", 38 "org.apache.catalina.LifecycleListener"); 3940//Executor41 digester.addObjectCreate("Server/Service/Executor", 42 "org.apache.catalina.core.StandardThreadExecutor", 43 "className"); 44 digester.addSetProperties("Server/Service/Executor"); 4546 digester.addSetNext("Server/Service/Executor", 47 "addExecutor", 48 "org.apache.catalina.Executor");
比如这里面的digester.addSetNext("Server","setServer","org.apache.catalina.Server")这句话,在Digester类中的实现如下:
1 public void addSetNext(String pattern, String methodName, 2 String paramType) { 3 4 addRule(pattern, 5 new SetNextRule(methodName, paramType)); 6 7 }
实现的内容就是把org.apache.catalina.Server以及setServer以SetNextRule的类型保存起来。看一下SetNextRule对象提供的方法,
其中end方法的实现如下:
public void end(String namespace, String name) throws Exception { // Identify the objects to be used Object child = digester.peek(0); Object parent = digester.peek(1); if (digester.log.isDebugEnabled()) { if (parent == null) { digester.log.debug("[SetNextRule]{" + digester.match + "} Call [NULL PARENT]." + methodName + "(" + child + ")"); } else { digester.log.debug("[SetNextRule]{" + digester.match + "} Call " + parent.getClass().getName() + "." + methodName + "(" + child + ")"); } } if(methodName.equals("setServer")){ System.out.println("111111111111111111"); } // Call the specified method IntrospectionUtils.callMethod1(parent, methodName, child, paramType, digester.getClassLoader()); }
在这里通过反射实现的方法调用。大家可能困惑到底是在哪发出rule.end调用动作的呢?下面还是要看一下Digester类,igester继承了org.xml.sax.ext.DefaultHandler2类,其中有一个endElement方法,这个方法在读完XML中每个Element的时候执行,看一下endElement方法在Digester中的实现:
@Override public void endElement(String namespaceURI, String localName, String qName) throws SAXException { boolean debug = log.isDebugEnabled(); if (debug) { if (saxLog.isDebugEnabled()) { saxLog.debug("endElement(" + namespaceURI + "," + localName + "," + qName + ")"); } log.debug(" match=‘" + match + "‘"); log.debug(" bodyText=‘" + bodyText + "‘"); } // Parse system properties bodyText = updateBodyText(bodyText); // the actual element name is either in localName or qName, depending // on whether the parser is namespace aware String name = localName; if ((name == null) || (name.length() < 1)) { name = qName; } // Fire "body" events for all relevant rules List<Rule> rules = matches.pop(); if ((rules != null) && (rules.size() > 0)) { String bodyText = this.bodyText.toString(); for (int i = 0; i < rules.size(); i++) { try { Rule rule = rules.get(i); if (debug) { log.debug(" Fire body() for " + rule); } rule.body(namespaceURI, name, bodyText); } catch (Exception e) { log.error("Body event threw exception", e); throw createSAXException(e); } catch (Error e) { log.error("Body event threw error", e); throw e; } } } else { if (debug) { log.debug(" No rules found matching ‘" + match + "‘."); } if (rulesValidation) { log.warn(" No rules found matching ‘" + match + "‘."); } } // Recover the body text from the surrounding element bodyText = bodyTexts.pop(); if (debug) { log.debug(" Popping body text ‘" + bodyText.toString() + "‘"); } // Fire "end" events for all relevant rules in reverse orderif (rules != null) { for (int i = 0; i < rules.size(); i++) { int j = (rules.size() - i) - 1; try { Rule rule = rules.get(j); if (debug) { log.debug(" Fire end() for " + rule); } if(name.equals("setServer")){ System.out.println("1222"); } rule.end(namespaceURI, name); } catch (Exception e) { log.error("End event threw exception", e); throw createSAXException(e); } catch (Error e) { log.error("End event threw error", e); throw e; } } } // Recover the previous match expressionint slash = match.lastIndexOf(‘/‘); if (slash >= 0) { match = match.substring(0, slash); } else { match = ""; } }
主要功能就是找出对应的rule来逐一调用rule.end方法。根据在Catalina.java类中digester添加的rule,就执行到了StandardServer类中的addService方法,设置的server对象,这部分内容很重要。
configFile:返回配置文件conf/server.xml文件。在获取配置文件conf/server.xml出错的时候,就尝试去获取server-embed.xml文件,如果都不存在,那么直接返回。记录日志。
initStreams:这个方法很简单只是做了一个tomcat自定义的流的重定向,
getServer().init:设置一下server的状态,然后初始化网络配置。
OK,load方法就说完了,很长。
然后在start方法中启动server。至于start方法,我们不再本文中说明,等在以后的章节会专门介绍Server。
然后在在当期运行环境中注册一个ShutdownHook,该钩子的作于就是当程序结束时候,将Catalina程序shutdown。
到此为止,start方法就算是说完了。其中主要内容就是如何构造一个server对象。在以后会展开说明Server对象。
Stop:另外一个被外部调用的方法就是stop方法,看一下stop方法的代码实现:
public void stop() { try { // Remove the ShutdownHook first so that server.stop() // doesn‘t get invoked twice if (useShutdownHook) { Runtime.getRuntime().removeShutdownHook(shutdownHook); // If JULI is being used, re-enable JULI‘s shutdown to ensure // log messages are not lost 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. } // Shut down the servertry { 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(); } } catch (LifecycleException e) { log.error("Catalina.stop", e); } }
首先要移除在start方法中注册的钩子,否则在程序结束以后再次触发钩子中定义的事件,肯定会出错。然后就获取server对象,检查状态,如果在运行那么停止,然后将资源释放。stop方法简单很多。
stopServer:先检查Server对象是否存在,如果不存在就创建一个新的,然后关闭server以及Server中定义的socket。
Catalina中的内容大概就这么多了,很不过瘾的地方就是内容很多,没有办法全部展开,尤其是实现Server接口的Server对象,构建server的方法,希望在下面的章节中把如何通过Digester构建server,以及与次有很重要关系的Tomca的结构比如server,services,connector,container等说清楚。
如果有不正确的地方请指正。大家共同学习。
原文:http://www.cnblogs.com/fantiantian/p/3651105.html
内容总结
以上是互联网集市为您收集整理的查看tomcat启动文件都干点啥---Catalina.java全部内容,希望文章能够帮你解决查看tomcat启动文件都干点啥---Catalina.java所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。