日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

tomcat(17)启动tomcat

發(fā)布時間:2023/12/3 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 tomcat(17)启动tomcat 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【0】README 1)本文部分文字描述轉自“how tomcat works”,旨在學習“tomcat(17)啟動tomcat”的相關知識; 2)本文重點關注啟動Tomcat時會用到的兩個類,分別是Catalina類和 Bootstrap類;(干貨——引入tomcat啟動時用到了兩個類,分別是Catalina類和 Bootstrap類) 2.1)org.apache.catalina.startup.Catalina類:用于啟動和關閉Server對象,并負責解析Tomcat 配置文件 server.xml; 2.2)org.apache.catalina.startup.Bootstrap類:是一個入口點,負責創(chuàng)建 Catalina實例,并調用其 process()方法; 3)理論上,這兩個類可以合二為一,但為了支持tomcat的多種運行模式,故提供了多種啟動類; 4)用戶只需要運行相應的批處理文件或shell 腳本即可啟動或關閉tomcat; 5)本文會intro 如何在Windows平臺 和 UNIX/Linux 平臺上運行tomcat; 6)本文總結了 tomcat啟動的調用過程,非常干貨,不得不感慨本篇博文產自于收獲的季節(jié).
【1】Catalina類(org.apache.catalina.startup.Catalina) 1)intro:它包含一個Digester類,用于解析位于 %CATALINA_HOME%/conf 目錄下的server.xml 文件;理解到tomcat(15)中 向Digester對象添加規(guī)則的原理后,就可以自行配置tomcat了;(干貨——理解到tomcat(15)中 向Digester對象添加規(guī)則的原理后,就可以自行配置tomct了,tomcat(15)Digester庫) 1.1)該類還封裝了一個Server對象(服務器組件,你是否有印象):該對象有一個Service對象(服務組件,你是否有印象);(干貨——服務器組件+服務組件,參見tomcat(14)服務器組件和服務組件) 1.2)Service對象包含有一個Servlet容器和一個或多個連接器。所以可以使用Catalina類來啟動或關閉Server對象; 2)可以通過實例化Catalina類,并調用其process()方法來運行tomcat; 3)universe 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"));} 對以上代碼的分析(Analysis): step1)process()方法設置了兩個系統(tǒng)屬性:catalina.home and catalina.base.catalina.home,默認值均為user.dir 屬性的值; step2)catalina.base == catalina.home ,所以,他們都與 user.dir 屬性的值相同; step3)隨后,process()方法會調用 arguments()方法(highlight line),并傳入參數列表; step4)intro to arguments()方法:arguments()方法處理命令行參數,如果Catalina對象能夠繼續(xù)處理的話,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 }");} step5)process()方法會檢查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() // doesn't 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);}}}}

對以上代碼的分析(Analysis): step1)該方法會創(chuàng)建一個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對象和其它的組件; Attention) A1)此外,start()方法還會利用關閉鉤子,確保用戶突然退出應用程序時會執(zhí)行Server.stop()方法; A2)start()方法會調用了createStartDigester 方法創(chuàng)建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 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");digester.addObjectCreate("Server/Service/Listener",null, // MUST be specified in the element"className");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 element"className");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()方法 1)intro:stop()方法用來關閉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); } Attention) A1)stop()方法:調用createStopDigester()方法來創(chuàng)建一個 Digester實例,并調用該實例的push()方法,并將當前Catalina對象壓入到 Digester對象的內部棧中,使用Digester對象解析tomcat 的配置文件; A2)然后,stop()方法會向正在運行的Server對象發(fā)送關閉命令,以關閉Server對象;
【1.3】啟動Digester對象 1)intro:Catalina.createStartDigester()方法創(chuàng)建了一個 Digester實例,然后為其添加規(guī)則,以解析server.xml文件;server.xml文件用來配置 tomcat,位于 ?%CATALINA_HOME%/conf目錄下。添加到Digester對象中的規(guī)則是理解tomcat配置的關鍵;(不能再干貨——添加到Digester對象中的關澤是理解tomcat配置的關鍵) 2)org.apache.catalina.startup.Catalina.createStartDigester()的源代碼如上所示: 因為該方法在start()方法中調用,我們在分析start方法的時候,已經分析過了;
對createStartDigester方法源代碼的分析(Analysis): step1)該方法會創(chuàng)建org.apache.commons.digester.Digestser類的實例,并為其添加規(guī)則(rules); step2)前3條規(guī)則用于解析 server.xml 文件的server元素。下面是為 server 模式添加的規(guī)則(因為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條規(guī)則表明:在遇到server元素時,Digester要創(chuàng)建 StandardServer 類的一個實例; rule2)第2條規(guī)則表明:要對 Server對象的指定屬性名設置同名的屬性值; rule3)第3條規(guī)則表明:將Server對象壓入到 Digester對象的內部棧中,并與棧中的下一個對象相關聯(lián)。 3)下一個對象是Catalina實例,調用其setServer()方法與 Server對象相關聯(lián)。那Catalina實例是如何防盜Digester 對象的內部棧中的呢? 在start()方法的開始部分,在解析 server.xml文件之前,會調用 Digester.push()方法將Catalina對象壓入棧: digester.push(this); 【1.4】 關閉Digetster對象 1)intro 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.Bootstrap) 1)intro:該類提供了啟動tomcat的入口點; 2)當運行startup.bat 文件或 startup.sh 文件時,實際上是調用了該類的main()方法。main方法會創(chuàng)建3個類載入器,并實例化Catalina類;然后它調用Catalina.process()方法; 3)Bootstrap類的定義如下: 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);} } 對以上代碼的分析(Analysis): A1)Bootstrap類有4個靜態(tài)方法:兩個log()方法,getCatalinaHome()方法 和 getCatalinaBase()方法; A2)getCatalinaHome()方法:其基本含義是,如果先前沒有設置過catalina.home 屬性的值,它就返回 user.dir屬性的值; A3)?getCatalinaBase()方法:基本含義是,如果catalina.base屬性的值為空,則返回 catalina.home屬性的值; A4)Bootstrap.main()方法中還會為不同目的而創(chuàng)建3個類載入器;使用多個類載入器的目的是為了防止應用程序中的類(包括servlet類和web 應用程序中的其他輔助類)使用 WEB-INF/classes目錄 和 WEB-INF/lib 目錄之外的類。部署到 %CATALINA_HOME%/common/lib 目錄下的那個 JAR 文件的類文件是可以使用的;(干貨——Bootstrap.main()方法中還會為不同目的而創(chuàng)建3個類載入器) 4)對3個類載入器進行詳細說明 4.0)三個類載入器的定義如下: // Construct the class loaders we will need ClassLoader commonLoader = null; ClassLoader catalinaLoader = null; ClassLoader sharedLoader = null; Attention)對于每個類載入器都會指定一條可以訪問的路徑; 4.1)commonLoader類載入器可以載入: %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.2)catalinaLoader類加載器負責載入運行 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.3)sharedLoader類可以載入: %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);}

Attention) A1)在tomcat中,每個 web 應用程序中與 Context容器相關聯(lián)的每個類載入器的父類載入器都是sharedLoader 類載入器; A2)sharedLoader類載入器并不能訪問 Catalina的內部類,或 CLASSPATH 環(huán)境變量指定的類路徑中的類; 5)在創(chuàng)建了3個類載入器之后,main()方法會載入Catalina類并創(chuàng)建它的一個實例,然后再將其賦值給 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 平臺上運行tomcat 1)可以調用 startup.bat或shutdown.bat?批處理文件來 啟動或關閉 tomcat;
【3.1】如何編寫批處理文件 Attention) A1)首先,批處理文件的后綴名必須是 “.bat”; A2)DOS 目錄及環(huán)境變量是區(qū)分大小寫的; 0)對批處理命令進行intro(commands): c1)rem: 該命令用于注釋。解釋器將不會執(zhí)行以rem 命令開始的行; c2)pause:該命令用于暫停正在執(zhí)行的批處理文件,并提示用戶按某個鍵,然后程序會繼續(xù)運行; c3)echo:該命令用于在dos 控制臺上顯示一段文本。例如,下面的命令將在控制臺上輸出“hello world”,然后暫停程序。之所以暫停程序是為了能夠使控制臺將輸出的文本顯示出來; echo hello world pause c3.1)如果想要顯示環(huán)境變量的值,需要在其的前后添加 %%;如,下面的目錄將輸出變量myVar的值: echo %myVar% c3.2)如果想要輸出操作系統(tǒng)的名字,可以使用如下的命令: echo %OS% c4)echo off:使用echo off 命令可以防止將批處理文件中的具體命令輸出,而只會輸出執(zhí)行結果。但是,“echo off”命令本身還是會顯示出來。如果想要將 “echo off”也隱藏起來,需要使用 @echo off 命令; c5)@echo off:該命令與 echo off 命令類似,但是他會連 echo off 命令也隱藏起來; c6)set:用來設置用戶定義或命名的環(huán)境變量。在批處理文件中設置的環(huán)境變量是臨時存儲在內存中的,在批處理文件執(zhí)行完成后就會銷毀; 看個荔枝)下面的set命令創(chuàng)建了一個名為 “usernmae”的環(huán)境變量,其值為“tang”,并輸出到console:
set username=tang echo %username% pause Attention)為了獲取變量的值,需要在變量前后添加“%”符號。如 “echo %username%”在字符串中就可以取到 username的值; c7)label:使用冒號設置一個標簽。然后可以將標簽傳遞給goto命令,這樣程序就會跳轉到標簽指定的位置。下面的語句定義了一個end的標簽:":end"; c8)goto:goto命令強制批處理文件跳轉到指定標簽所在的位置繼續(xù)執(zhí)行 看個荔枝) echo start goto end echo i am a student; :end echo end pause
對以上腳本的分析(Analysis):在第1行輸出start后,批處理文件會執(zhí)行 goto命令,跳轉到end標簽處; c9)if:if用來測試條件測試,有3種用法(func):(干貨——if命令用來測試條件測試,有3種用法) if variable==value nextCommand func1)測試變量的值; set myVar=3 if %myVar%==3 echo Correct func2)測試文件是否存在; if exist c:\temp\myFile.txt goto start; func3)測試錯誤值; set myVar=3 if not %myVar%==3 echo Correct
c10)not:not關鍵字用來對一條語句取反; c11)exist:當測試文件是否存在時,會使用到 if 和 exist命令; c12)接收參數:可以給批處理文件傳遞參數,并使用%1 引用第1個參數,%2 引用第2個參數,以此類推; c12.1)echo %1:將在console 輸出 第1個參數的值;(如果批處理文件的名字是 test.bat,并使用 “test hello” 命令來調用它,那么將會在console中輸出 “hello”); 看個荔枝)下面的文件會對第1個參數進行檢查。如果是start,輸出“start”;如果是stop,輸出stop;否則,輸出invalid; echo off if %1==start goto start if %1==stop goto stop go invalid :start echo start go end :stop echo stop goto end :invalid echo invalide :end
Attention)若要檢查運行批處理文件時,是否帶有參數,可以將 %1 與 空字符串進行比較。如,對于下面的批處理文件,如果運行時沒有使用參數,就會在控制臺上輸出“no parameter”; if "%1"=="" echo no parameter orif ""%1""=="""" echo no parameter c13)shift:shift命令用來將參數向后移動一位,即將%2的值復制給%1,%3的值復制給%2,以此類推;例如,下面的代碼使用一條shift命令: echo off shift echo %1 echo %2 如果在運行批處理文件時,附加了3個參數a,b和c,那么上面的命令會有如下輸出: b c 移動之后,要使用 %0 來應用第1個參數,而現在最后一個參數已經失效了; c14)call:該命令用來調用另一條命令; c15)setLocal:在批處理文件中使用 setLocal對環(huán)境變量的修改只在當前批處理腳本中有效。當遇到endLocal 命令后,在批處理文件的末尾修改的環(huán)境變量的值會恢復成原來的值; c16)start:打開一個新的Windows控制臺,并可以為這個新的控制臺指定一個名字,如:?start "title" ;此外,在 title后面,還有傳入一條將要在新的控制臺中執(zhí)行的目錄,如下所示: start "title" commandName;
【3.2】 catalina.bat 批處理文件 1)catalina.bat 批處理文件用來啟動或關閉tomcat。另外兩個文件(startup.bat 和 shutdown.bat)提供了更簡單地啟動和關閉tomcat的方法。實際上,startup.bat 和 shutdown.bat 都會調用catalina.bar 文件,并傳入相應的參數; 2)在%CATALINA_HOME%/bin 目錄下,需要以下面的語法格式調用 catalina.bar 腳本: catalina? 會使用下面的語法 從 %CATALINA_HOME%/bin 目錄下調用該腳本: bin\catalina 3)在兩種case下,參數command 的可選值包括: c1)debug:在調試器中啟動 Catalina; c2)debug -security;在使用安全管理器的case下調試 Catalina; c3)embedded:以嵌入模式啟動Catalina; c4)jpda start:在 JPDA調試器下啟動 Catalina; c5)run:在當前窗口中啟動 Catalina; r6)run -security:在當前窗口中,通過安全管理器啟動 Catalina; r7)start:在新窗口中啟動 Catalina; r8)start -security:在新窗口中通過安全管理器啟動 Catalina; r9)stop:關閉Catalina; 看個荔枝)想在新窗口中啟動 Catalina,可以使用如下命令:catalina start;
4)catalina.bat 批處理文件的內容: ?https://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/catalina.bat 對catalina.bat 文件的分析(Analysis):暫時省略
Supplement) Supplement1)catalina.bat 文件中,通過設置MAINCLASS==org.apache.catalina.startup.Bootstrap,然后在該bat文件末尾會運行該類(Bootstrap) set MAINCLASS=org.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(不能再干貨) step1)startup.bat 批處理文件會調用 catalina.bat 文件,而catalina.bat批處理會運行org.apache.catalina.startup.Bootstrap 類(main方法); step2)Bootstrap.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(); // 創(chuàng)建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 version='1.0' encoding='utf-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 port="8005" shutdown="SHUTDOWN"><!-- Security listener. Documentation at /docs/config/listeners.html<Listener className="org.apache.catalina.security.SecurityListener" />--><!--APR library loader. Documentation at /docs/apr.html --><Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" /><!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html --><Listener className="org.apache.catalina.core.JasperListener" /><!-- Prevent memory leaks due to use of particular java/javax APIs--><Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /><Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" /><Listener className="org.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 name="UserDatabase" auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/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 name="Catalina"><!--The connectors can use a shared executor, you can define one or more named thread pools--><!--<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"maxThreads="150" minSpareThreads="4"/>--><!-- 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 port="8888" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" /><!-- A "Connector" using the shared thread pool--><!--<Connector executor="tomcatThreadPool"port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />--><!-- 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 port="8443" protocol="HTTP/1.1" SSLEnabled="true"maxThreads="150" scheme="https" secure="true"clientAuth="false" sslProtocol="TLS" />--><!-- Define an AJP 1.3 Connector on port 8009 --><Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /><!-- 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 name="Catalina" defaultHost="localhost" jvmRoute="jvm1">--><Engine name="Catalina" defaultHost="localhost"><!--For clustering, please take a look at documentation at:/docs/cluster-howto.html (simple how to)/docs/config/cluster.html (reference documentation) --><!--<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>--><!-- Use the LockOutRealm to prevent attempts to guess user passwordsvia a brute-force attack --><Realm className="org.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 className="org.apache.catalina.realm.UserDatabaseRealm"resourceName="UserDatabase"/></Realm><Host name="localhost" appBase="webapps"unpackWARs="true" autoDeploy="true"><!-- SingleSignOn valve, share authentication between web applicationsDocumentation at: /docs/config/valve.html --><!--<Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example.Documentation at: /docs/config/valve.htmlNote: The pattern used is equivalent to using pattern="common" --><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"prefix="localhost_access_log." suffix=".txt"pattern="%h %l %u %t "%r" %s %b" /></Host></Engine></Service> </Server> 對以上server.xml代碼的分析(Analysis): A1)創(chuàng)建一個服務器組件; A1.1)服務器組件里面注入多個監(jiān)聽器,資源(GlobalNamingResources A1.2)創(chuàng)建一個服務組件; A1.2.1)創(chuàng)建兩個Connector; A1.2.2)創(chuàng)建一個Engine,Engine中注入兩個領域對象(Realm);還注入了一個Host容器;和一個閥; Attention) A1)服務器組件和服務組件,參見 tomcat(14)服務器組件和服務組件; A2)Digester用于將XML 文檔中的元素轉換成 java 對象,參見?tomcat(15)Digester庫

Conclusion)(不能再干貨——tomcat的啟動調用過程review)

C1)自此,tomcat的啟動調用過程我們已經分析完畢,再review 一下: startup.bat -> catalina.bat -> Bootstrap.main() -> Catalina.process() -> ?createStartDigester() ->configFile() ;

C2)啟動createStartDigester方法會創(chuàng)建Digester類,用于將server.xml 中的元素轉換為java對象;而configFile方法就是用于設定 將要解析的xml的文件路徑的.



【3.3】在Windows 平臺上啟動tomcat(startup.bat 文件調用catalina.bat 文件時,會傳入參數 start) https://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/startup.bat
【3.4】在Windows 平臺上關閉tomcat(shutdown.bat 文件調用 catalina.bat文件時,傳入參數 stop) https://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/shutdown.bat


【4】在Linux平臺上啟動Tomcat 1)在linux平臺上,tomcat使用shell 腳本來啟動和關閉。shell腳本的后綴名可以是 “.sh”,位于 $CATALINA_HOME/bin 目錄下; 2)intro:本章節(jié)將intro 4 個腳本:catalina.sh, statup.sh, shutdown.sh, setclasspath.sh;
【4.1】如何編寫UNIX/Linux Shell腳本 1)intro:shell腳本是由解釋器逐行執(zhí)行的,shell 腳本的擴展名可有可無,但最常用的擴展名是 .sh; 2)下面簡單介紹下 shell 命令(command): c1)注釋:shell腳本使用 # 符號來表示注釋內容; c2)clear:使用該命令來清空屏幕; c3)exit:該命令可以用來退出當前shell 腳本的執(zhí)行;一般case下,exit后面都會附加一個退出狀態(tài),其中0 表示shell腳本正常執(zhí)行完成,非0值表示shell異常退出;如果因為程序運行中的某種異常而想退出,使用如下命令:exit 1;(干貨——exit后面都會附加一個退出狀態(tài),其中0 表示shell腳本正常執(zhí)行完成,非0值表示shell異常退出) c4)echo:該命令可以向屏幕輸出一個字符串:echo hello world; c5)調用函數:可以使用句點(.)來調用一個函數,或執(zhí)行另一個shell 腳本; c6)系統(tǒng)變量與用于自定義變量:變量名必須以字母,數字或下劃線開頭,使用等號就可以定義一個變量;如下面的命令定義了一個名為 myVar 的變量,其值為 Tootsie:myVar=Toosie; Attention) A1)等號的前后一定不能有空格。此外,shell 腳本對變量名是區(qū)分大小寫的 ; A2)若想定義一個值為NULL的變量,可使用空字符串為其賦值,或在等號右邊留空即可: myVar= myVar="" A3)若想要獲取變量的值,需要在變量前面加上美元符號($):echo $myVar A4)Unix/Linux 提供了一些系統(tǒng)變量供用戶使用;如,變量HOME 保存了當前用戶的主目錄,變量PWD 保存了用戶當前所在的目錄,變量PATH 保存了將會在哪些地方查找要執(zhí)行的命令等; c7)expr: 可以使用該命令來計算一個表達式的值。表達式必須以反引號引用;如下面的shell 腳本計算一個數學表達式: sum=`expr 100+200` echo $sum c7.1)腳本:echo `expr 200+300` 會輸出500; c7.2)特殊表達式`uname`會得到操作系統(tǒng)的名稱:echo `uname` 會輸出操作系統(tǒng)名稱(Linux或Unix); c7.3)特殊表達式 `dirname filePath` 會返回指定文件所在的目錄。如,命令 `dirname /home/user1/test.sh` 會返回“home/user1”; c8)訪問參數:如同向函數中傳入參數一樣,也可以向shell腳本傳入參數,并使用 $1 來引用第1個參數,$2引用第2個參數,以此類推;$# 會返回參數的格式,$@會返回所有的參數; c9)shift:這條命令會將參數向后移動一位,$1的值改為 $2, $2的值改為$3, 以此類推; c10)if...then...[else...] fi:if 語句用來測試條件,并執(zhí)行相應的命令列表。它的語法格式如下: 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 Attention)
A1)判斷條件在 “[” 后面必須有一個空格, 在“]”前面也必須有一個空格; A2)將 $1 用雙引號引起來可以防止解釋器在發(fā)現調用腳本時沒有使用參數而拋出異常; 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; c11)for循環(huán):使用for循環(huán)來重復執(zhí)行一些命令: for {var} in {list} dolist of commands done 看個荔枝)
for i in 1 2 3 doecho i=$i done output: i1 i2 i3 c12)while循環(huán): while [condition] dolist of commands done
看個荔枝)
n=1 while [$n -lt 3] doecho i $n done output: i1 i2 Attention)其中 [$n -lt 3];中 -lt 的意思是小于3,(lt == less than) c13)case:case結構表示可以在程序中執(zhí)行一些選擇過程。其語法格式如下所示: case $variable-name in pattern1)list of commands;; pattern2)list of commands;; *)list of commands;; esac Attention)“;;”表示命令列表執(zhí)行完成,如果上面的模式都不匹配時,“*)”表示所要執(zhí)行的命令; 看個荔枝) case "`uname`" inCYGWIN*)echo cygwin;;OS400*)echo os400;;LINUX*)echo linux;;*)echo os not recognized;; esac c14)輸出重定向(review):使用 “>”將輸出重定向到一個文件;(echo hello > myFile.txt);這會創(chuàng)建一個 myFile.txt的文件,并將 hello 寫入到其中,不會向屏幕上輸出文字; Supplement) S1)"1>&2":會把標準輸出上的錯誤消息重定向到標準錯誤中; S1)"2>&1":會把標準錯誤中的信息重新向到 標準輸出中;
c15)條件執(zhí)行:可以使用命令或條件來決定是否執(zhí)行另一條命令。在這種 case下, 可以使用 && 或 || ,如下所示: c15.1)command1 && command2:如果command1返回的退出狀態(tài)是0,那么會執(zhí)行command2;(0表true,非0表false) c15.2)command1 || command2:如果command1返回的退出狀態(tài)是非0,那么會執(zhí)行command2;(0表true,非0表false) c15.3)command1 && command2 || command3:如果command1返回的退出狀態(tài)是非0,那么會執(zhí)行command2;否則,執(zhí)行command3;(0表true,非0表false);
【4.2】catalina.sh 腳本 1)intro: 該文件用來在 UNIX/Linux 平臺上啟動或關閉tomcat。若要啟動tomcat,需要將 start作為第1個參數傳遞給 catalina.sh 腳本。若要關閉 tomcat,需要將stop 作為第1個參數傳遞給 catalina.sh腳本。下面是有效的 參數列表(parameters): p1)debug:在調試器中啟動catalina;(在OS400系統(tǒng)上不可用) p2)debug -security:通過安全管理器調試catalina;(在OS400系統(tǒng)上不可用) p3)embedded:以嵌入模式啟動 Catalina; p4)jpda start:在JPDA 調試器下啟動 Catalina; p5)run:在當前窗口中啟動 Catalina; p6)run -security:在安全管理器下,使用當前窗口啟動 catalina; p7)start:使用一個新窗口啟動 catalina; p8)start -security:在安全管理器下,使用一個新窗口啟動 catalina; p9)stop:關閉 catalina; 2)catalina.sh 的源代碼,參見: ?https://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/catalina.sh
【4.3】在 unix/linux 平臺上啟動 tomcat 1)使用 startup.sh 腳本可以方便地啟動 tomcat。startup.sh 腳本會設置正確的環(huán)境變量,然后調用 catalina.sh腳本,并傳入參數 start: ?https://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/startup.sh
【4.4】在 unix/linux 平臺上關閉 tomcat 1)使用 shutdown.sh 腳本可以方便地啟動 tomcat。shutdown.sh 腳本會設置正確的環(huán)境變量,然后調用 catalina.sh腳本,并傳入參數 stop: ?https://github.com/pacosonTang/HowTomcatWorks/blob/master/chapter17/shutdown.sh
------------------------------------------------------------------------------------------------------ Supplement)文末繼續(xù)對 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 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");digester.addObjectCreate("Server/Service/Listener",null, // MUST be specified in the element"className");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 element"className");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 element"className");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 element"className");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 element"className");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 element"className");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 element"className");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 element"className");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 element"className");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 element"className");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 element"className");digester.addSetProperties(prefix + "Host/Valve");digester.addSetNext(prefix + "Host/Valve","addValve","org.apache.catalina.Valve");}public void addRuleInstances(Digester digester) { //<span style="font-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 element"className");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 element"className");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 element"className");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 element"className");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 element"className");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): A1)EngineRuleSet.addRuleInstances()方法:創(chuàng)建Engine容器StandardEngine,Engine監(jiān)聽器EngineConfig, 聲明周期監(jiān)聽器?LifecycleListener, 日志Logger, 領域對象Realm, 管道閥對象?Valve; A2)HostRuleSet.addRuleInstances()方法:創(chuàng)建Host容器StandardHost, Host監(jiān)聽器HostConfig, 集群Cluster, 生命周期監(jiān)聽器LifecycleListener,?日志Logger, 領域對象Realm, 管道閥對象?Valve; A3)ContextRuleSet.addRuleInstances()方法:創(chuàng)建Context容器?StandardContext, Context監(jiān)聽器ContextConfig, 生命周期監(jiān)聽器LifecycleListener,Web加載器WebappLoader, 管理器Manager,?Store, 領域對象Realm,?ContextResourceLink, 管道閥對象Valve,

總結

以上是生活随笔為你收集整理的tomcat(17)启动tomcat的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

中中文字幕av在线 | 亚洲激色 | 日韩精品视频在线观看免费 | 国产色婷婷精品综合在线手机播放 | 日韩国产精品久久久久久亚洲 | 色是在线视频 | av专区在线| 东方av免费在线观看 | 又污又黄网站 | 久久久蜜桃一区二区 | 精品久久九九 | 欧美日韩不卡在线 | 91麻豆精品国产自产在线游戏 | 中文字幕av一区二区三区四区 | 97人人澡人人添人人爽超碰 | 狠狠干成人综合网 | 色永久免费视频 | 91在线观看视频网站 | 亚洲一级黄色 | 精品久久久久一区二区国产 | 国产精品久久精品国产 | 日韩欧美视频免费看 | 欧美在线视频一区二区三区 | 精品久久久久久久久久久院品网 | 久久精品播放 | 91成人免费观看视频 | 亚洲黄电影 | 五月丁色 | 中文字幕 二区 | 欧美一区二区日韩一区二区 | 国产麻豆精品久久一二三 | 黄色av一区 | 精品国产一区二区三区蜜臀 | 伊人五月天综合 | 久草视频一区 | 免费三级大片 | 99久久成人| 国产69精品久久99不卡的观看体验 | 国产精品人成电影在线观看 | 国产成人一级 | 91av视屏 | 午夜a区| 日黄网站 | 久久xxxx| 中文字幕色在线视频 | 欧美性黄网官网 | 亚洲欧美精品在线 | 日韩黄色在线电影 | 91精品999| 在线观看av网站 | 在线亚洲精品 | 国产精品免费人成网站 | 国产一二区在线观看 | 激情婷婷综合网 | 国产精品精品国产色婷婷 | 水蜜桃亚洲一二三四在线 | 国产精品岛国久久久久久久久红粉 | 超碰97久久| 伊人精品影院 | 国产视频在线观看一区 | 精品国产一区二区三区久久 | 亚洲免费成人av电影 | 日韩视频免费看 | 天天天天天天天天操 | 中文在线字幕观看电影 | 亚洲一级黄色大片 | 一区二区三区精品在线视频 | 日韩一区二区免费视频 | 精品免费久久久久 | 久久精品国产精品亚洲 | 精品国产伦一区二区三区观看体验 | 国产精品地址 | 国产视频在线观看一区 | 亚洲五月 | 亚洲精品成人av在线 | 91在线观| 国产精品成人一区二区三区吃奶 | 国内精品久久久久影院一蜜桃 | 在线观看麻豆av | 在线观看视频福利 | 久久色网站| 久久视频免费在线 | 最近中文字幕大全 | 亚洲国产精品一区二区久久,亚洲午夜 | 午夜精品一区二区三区视频免费看 | 人人干人人上 | 久草综合在线 | 4438全国亚洲精品在线观看视频 | 99久久国产免费看 | 久久婷婷视频 | 中文字幕一区二区三区久久 | 午夜精品久久久久久久99 | 五月婷婷在线观看视频 | 亚洲激情综合 | 日产av在线播放 | 亚洲视频网站在线观看 | 久久精品99国产精品酒店日本 | 500部大龄熟乱视频使用方法 | 久久免费资源 | 中国一级片视频 | 久99久精品视频免费观看 | av黄色在线播放 | 精品二区久久 | 日韩精品一区二区三区高清免费 | 久草久视频 | 国产精品观看视频 | 天天看天天干 | 射射色 | 色婷婷激情| 97av视频在线观看 | 久久久久久久久久免费视频 | 在线看欧美| 中文字幕电影一区 | 亚洲人人射| 国产又粗又猛又爽又黄的视频先 | av片子在线观看 | 日韩网站在线免费观看 | 国产视频一区二区三区在线 | 又黄又爽免费视频 | 久久曰视频 | 久久人人爽人人 | 久草在线免费新视频 | 五月婷婷在线观看视频 | 免费看一级 | 免费视频成人 | 亚洲视频高清 | 99免费精品视频 | 一级片免费视频 | 91成人精品一区在线播放 | 久久综合久久88 | 狠狠网亚洲精品 | 色美女在线 | 国产精品久久久久影院日本 | 国产aaa大片 | 欧美激情va永久在线播放 | 国产区精品视频 | 91激情视频在线 | 色婷在线 | av在线之家电影网站 | 久久草网 | 久久久免费精品国产一区二区 | 97精品视频在线播放 | 欧美大香线蕉线伊人久久 | 日本精品在线视频 | 精品日韩中文字幕 | 日韩激情网 | 久久97超碰| 久久精品国产亚洲a | 国产精品免费观看视频 | 色噜噜狠狠狠狠色综合 | 亚洲日本精品视频 | 成年人免费在线观看网站 | 超碰国产在线 | 国产打女人屁股调教97 | 久草精品视频在线看网站免费 | 婷婷av网站| 亚洲精品乱码白浆高清久久久久久 | 色综合久久天天 | 激情在线免费视频 | 久久免费视频一区 | 天天操夜夜摸 | 亚洲国产色一区 | 久久综合久久综合这里只有精品 | 欧美成人视 | 国产精品观看视频 | 亚洲综合网 | 天天鲁一鲁摸一摸爽一爽 | 国产精品欧美久久久久久 | 国产精品久久久 | 激情综合色综合久久综合 | 久久99精品久久久久久 | www.av免费观看 | 久久人人爽爽人人爽人人片av | 亚洲欧美经典 | 99精品在这里 | 国产99久久久国产精品免费看 | 成年免费在线视频 | 国产在线观看一区 | 三上悠亚一区二区在线观看 | 国产精品一区二区久久精品爱微奶 | 最新av免费在线 | 久亚洲 | 亚洲va欧美va人人爽春色影视 | 4438全国亚洲精品观看视频 | 天天色天天操综合 | 91视频黄色 | 午夜久久久久久久 | 免费黄色在线播放 | 天天干中文字幕 | 亚洲麻豆精品 | 国产美女网 | 亚洲毛片久久 | 久久久久五月天 | 网站免费黄色 | 久久国产热视频 | 狠狠艹夜夜干 | 日韩欧美视频免费观看 | 99精品影视 | 欧美少妇xxx | 欧美男男激情videos | 欧美性大战| 综合中文字幕 | 日韩久久久久久久 | 在线亚洲成人 | 丁香免费视频 | 国产精品久久久久久久久久新婚 | 欧美久久久久久 | 久久亚洲综合色 | se视频网址 | 久久成人一区二区 | 视频在线观看入口黄最新永久免费国产 | 国产精品乱码久久久久 | 黄色免费网 | 91porny九色91啦中文 | 中文字幕在线播放视频 | 国产一级黄色免费看 | 九九热免费精品视频 | 500部大龄熟乱视频使用方法 | 13日本xxxxxⅹxxx20 | 久久这里只有精品23 | 日韩中文三级 | 日本中文字幕免费观看 | 天天se天天cao天天干 | 91理论片午午伦夜理片久久 | 天天干天天射天天操 | 天天干 天天摸 天天操 | 亚洲在线网址 | 九九热免费在线观看 | www.久久久.com| 国产一区自拍视频 | 国产精品美女久久久久久久久 | 四虎影视精品 | 国产免费人成xvideos视频 | 欧美一级片在线免费观看 | 国产精品久久久久久久毛片 | 韩国精品在线观看 | 精品国产欧美一区二区 | 国产在线精品视频 | 国产一区二区在线免费观看 | 在线播放国产一区二区三区 | 97精品国产97久久久久久久久久久久 | 欧美日韩一区久久 | 在线国产欧美 | 91精品啪 | 91香蕉视频色版 | 黄色av大片| 五月天婷婷丁香花 | 日韩av资源站 | 极品国产91在线网站 | 欧美精品久久久久久久久久白贞 | 国产va饥渴难耐女保洁员在线观看 | 在线国产一区二区三区 | 国产精品一区在线观看 | 国产亚洲精品久久久久久大师 | a视频免费在线观看 | 五月婷综合 | 97国产精品一区二区 | 天天插日日射 | 亚洲午夜精品一区二区三区电影院 | 亚洲手机av | 久久久国产精品久久久 | 欧美精品一区在线 | 日韩精品久久久久久久电影竹菊 | 国产999视频在线观看 | 日韩不卡高清视频 | 91少妇精拍在线播放 | 中文字幕在线观看91 | 日韩videos高潮hd | 亚洲精品乱码久久久久久写真 | 草久热| 国产午夜精品一区 | 色国产视频 | 亚洲欧洲精品一区二区精品久久久 | 免费一级片视频 | 精品国产一区二区三区久久 | 久久成视频 | 免费看污网站 | 波多野结衣在线视频一区 | 9999激情 | 久久免费在线观看视频 | 激情欧美一区二区免费视频 | 久久久999精品视频 国产美女免费观看 | 精品一区电影 | 在线日韩中文 | 啪啪免费观看网站 | 国产一区二三区好的 | 精品一二三四在线 | 久久久久电影 | 一区二区三区免费在线观看视频 | 婷婷中文在线 | 色a在线观看 | 尤物97国产精品久久精品国产 | 精品你懂的 | 亚洲国产中文字幕在线视频综合 | 成人97视频一区二区 | 国产视频一二三 | 精品九九九 | 97视频人人澡人人爽 | 最新亚洲视频 | 精品久久久精品 | 国产999精品久久久久久 | 日韩在线视频线视频免费网站 | 91热精品| 欧美午夜理伦三级在线观看 | 天天综合天天做天天综合 | 欧美精品网站 | 在线视频成人 | 91精品国产三级a在线观看 | 最新国产精品拍自在线播放 | 日韩免费不卡视频 | 精品国产一区二区三区四 | 又黄又爽又刺激 | 精品国产区在线 | 国产精品12 | 日韩毛片在线免费观看 | 国产精品久久久久久一区二区 | 99九九热只有国产精品 | 国内视频一区二区 | 三级av网站 | 国产91对白在线 | 国产一区久久 | 亚洲最大av网站 | 一级欧美一级日韩 | 97人人人人 | www.777奇米| 久久久www成人免费精品张筱雨 | 在线免费看片 | 激情久久久久久久久久久久久久久久 | 日韩欧美一区二区三区免费观看 | 欧美精品日韩 | 久久久久福利视频 | 免费影视大全推荐 | 欧美日韩免费网站 | 国产精品久久久久久久久婷婷 | 久久99免费 | 69精品在线观看 | 天天干天天做天天操 | 99久久久久免费精品国产 | 超碰公开97| 玖玖玖国产精品 | 日韩在线国产精品 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 久艹视频在线观看 | 激情五月在线视频 | 久久国产午夜精品理论片最新版本 | 精品久久久久久久久久岛国gif | 久久精品国产免费看久久精品 | 99tvdz@gmail.com| 国产一区二区久久久久 | 狠狠色丁香婷婷综合久小说久 | 日韩av成人在线观看 | 98涩涩国产露脸精品国产网 | 五月婷婷久久丁香 | www.夜夜干.com| 成年人av在线播放 | 久草视频播放 | 国产精品视频免费 | 久久国产高清 | 欧美成人猛片 | 国产精品欧美久久 | 中文字幕一区二区三区四区 | 日韩一级黄色片 | 久久国产精品一二三区 | 成人免费av电影 | 国产一区91 | 久久一精品 | 黄色国产在线 | 国产在线小视频 | 日一日操一操 | 黄色软件视频网站 | 日韩夜夜爽 | 久久久久久久久免费视频 | 亚洲 欧美 变态 国产 另类 | 午夜美女福利 | 9幺看片 | 免费观看视频的网站 | 激情五月亚洲 | 国内久久| 日韩在线播放av | 亚洲自拍自偷 | 成人动图| 视频国产在线观看18 | 天天操夜夜曰 | 99福利片 | 色视频在线| 精品一区二区在线播放 | av免费网站在线观看 | 偷拍区另类综合在线 | 日韩激情三级 | 国产激情电影综合在线看 | 91视频下载 | 国产午夜精品一区二区三区四区 | 国产视频色 | 国产中文欧美日韩在线 | 国产精品久久久99 | 日本三级香港三级人妇99 | 国产中文字幕在线 | 亚洲国产精品激情在线观看 | 99久热在线精品 | 久久久久国产一区二区三区 | www178ccom视频在线 | 欧美人人 | 特及黄色片 | 亚洲 成人 一区 | 国产123区在线观看 国产精品麻豆91 | 人人爽人人 | 久久激情视频免费观看 | 最新动作电影 | 青青草久草在线 | 欧美一级免费黄色片 | 一本一本久久a久久精品牛牛影视 | 狠狠插狠狠干 | 超碰国产在线播放 | 欧美精品一区二区三区一线天视频 | 成人在线观看资源 | 99视频国产精品免费观看 | 91新人在线观看 | 国产亚洲片 | aaawww | 久久视频在线视频 | 精品国产视频在线观看 | 欧美 亚洲 另类 激情 另类 | 久久污视频 | 久久久亚洲国产精品麻豆综合天堂 | 国产白浆视频 | 天天操网址 | 婷婷久久亚洲 | 欧美日韩久久不卡 | 国产99一区二区 | 国产精品自产拍在线观看桃花 | av九九九| 亚洲精品午夜久久久久久久久久久 | 五月精品 | 亚洲精品美女久久久 | 香蕉视频在线免费 | 日韩欧美在线观看一区二区 | 国产精品高清免费在线观看 | 久久久久久久久久久福利 | 日日干天天插 | 亚洲精品乱码久久久久久久久久 | 人人涩 | 久久精品国产免费 | 日韩乱码在线 | 成片视频免费观看 | 国产福利免费看 | 欧美久久精品 | 国产精品久久片 | www.色五月.com | 亚洲涩涩网 | 日本高清久久久 | 日日夜夜国产 | 日韩网站中文字幕 | 97在线影视 | 视频一区二区精品 | 国产精品永久在线 | 九九热中文字幕 | 婷婷综合伊人 | 亚洲热视频 | 天天操天天色天天射 | 欧美日韩精品在线免费观看 | 国产福利一区二区三区在线观看 | 国产麻豆精品一区二区 | 日韩欧美高清一区二区三区 | 人人插人人射 | 日韩在线免费观看视频 | 欧美极度另类性三渗透 | 正在播放日韩 | 在线视频 精品 | 西西www4444大胆在线 | 毛片网站免费 | 色综合天天色 | 91在线精品一区二区 | 亚洲精品小视频 | 久久国产欧美日韩精品 | 青青河边草免费视频 | 又黄又爽的视频在线观看网站 | 成人av播放| 国产91成人 | 激情视频一区二区三区 | 欧美不卡在线 | 在线视频电影 | 国产va饥渴难耐女保洁员在线观看 | 国产xvideos免费视频播放 | 久久久久久毛片精品免费不卡 | 欧美一区中文字幕 | 国产丝袜制服在线 | 久久九九影院 | 久久看片网站 | 亚洲人人爱 | 九九国产精品视频 | 成人黄色在线播放 | 日日操操 | 久草在线免费电影 | 在线中文字幕一区二区 | 夜夜看av| 操操操日日 | 久久精品99国产 | 久久精品亚洲精品国产欧美 | 国产日韩欧美在线 | 综合亚洲视频 | 五月婷婷综合激情 | 成人中文字幕av | 亚洲视频免费在线观看 | 国产麻豆果冻传媒在线观看 | 91在线影视 | 人人爽人人澡人人添人人人人 | 中文字幕在线久一本久 | 97国产精品亚洲精品 | 日韩欧美视频免费在线观看 | 欧美日韩国产精品一区二区亚洲 | 五月婷激情 | 亚洲精品中文字幕视频 | 韩日三级在线 | 黄色一级大片在线免费看国产一 | 成人avav | 日韩精品在线观看视频 | 中文字幕a∨在线乱码免费看 | 最近中文国产在线视频 | 亚洲精品久久视频 | 国产成人三级一区二区在线观看一 | 国产香蕉97碰碰碰视频在线观看 | 九九精品视频在线观看 | 国产在线高清视频 | 久久天天躁狠狠躁亚洲综合公司 | 91看片黄色 | 亚洲精品视频网站在线观看 | 国产高清无av久久 | 久久九九影院 | 在线黄色av电影 | 在线看中文字幕 | 深夜国产在线 | 久久免视频 | 天天射色综合 | 天天操综合网 | 麻豆国产网站入口 | 亚洲精品欧美视频 | 天堂av影院 | 成人在线免费视频 | 欧美成亚洲| 人人添人人澡人人澡人人人爽 | 久久久精品高清 | 最新中文在线视频 | 亚洲午夜久久久综合37日本 | 久久精品中文字幕免费mv | 2019中文最近的2019中文在线 | 成人午夜电影免费在线观看 | 国产又粗又硬又爽视频 | 波多野结衣电影一区 | 又爽又黄在线观看 | 久久人人爽av | 成人亚洲精品久久久久 | 日韩在线激情 | 久久久免费精品国产一区二区 | 综合久久影院 | 久久久国产精品一区二区三区 | 亚洲日本在线一区 | 国产一区二区在线影院 | 中文字幕免费成人 | 91漂亮少妇露脸在线播放 | 黄色毛片视频免费观看中文 | 黄色av成人在线观看 | 免费高清在线视频一区· | 91av视频网| 久久精品99国产精品亚洲最刺激 | 国产精品久久毛片 | 在线精品视频免费播放 | 久久特级毛片 | 中文字幕在线看视频国产中文版 | 国产色a在线观看 | 国产日本亚洲 | 丁香婷婷激情啪啪 | 国产精品成人在线 | 国产视频色 | 色网影音先锋 | 亚洲精品视频免费观看 | 国产高清小视频 | 特级黄色电影 | 亚洲国产精彩中文乱码av | 日韩不卡高清 | 97在线观看免费观看 | 成人免费视频网站 | 婷婷成人综合 | 丁香久久久 | 一区二区成人国产精品 | 日本aaa在线观看 | 在线不卡视频 | 久久精品一 | 国产精品一区二区久久久久 | 国产精品久久久久免费a∨ 欧美一级性生活片 | 中文区中文字幕免费看 | 黄色小说免费观看 | 色偷偷88888欧美精品久久 | 亚洲国产精品人久久电影 | 毛片播放网站 | 国产成人不卡 | 97视频免费播放 | 久久超级碰| 五月婷婷一区 | 999国内精品永久免费视频 | 97日日碰人人模人人澡分享吧 | 久久久免费观看完整版 | 黄色成人影视 | 久久艹国产视频 | 亚洲一区欧美精品 | 久久精品美女 | 日本在线观看一区二区 | 国产精品手机视频 | 特片网久久 | 久久av中文字幕片 | 黄色av高清 | 免费在线观看黄 | 免费av观看网站 | 欧美性色19p | 国产不卡在线 | 亚洲免费色 | 日韩视频二区 | 九九有精品 | 精品国产一区二区三区蜜臀 | 免费黄在线看 | 亚洲最大免费成人网 | 色综久久| 国产一级免费视频 | 国产片网站 | 日韩精品一区在线播放 | 日日天天av| 综合网婷婷 | 日韩精品一区二区三区视频播放 | 成人黄色电影在线播放 | 日本三级在线观看中文字 | 一本一本久久a久久精品综合 | 日韩手机视频 | 中文字幕在线播放一区二区 | 免费观看成人 | 国产精品网站一区二区三区 | 亚洲天天在线日亚洲洲精 | 国产精品久久久久久久久久免费看 | 国产成人免费精品 | 免费黄色看片 | 999久久国精品免费观看网站 | 国内精品久久久久影院优 | 天天综合导航 | 在线观看理论 | 欧美日产在线观看 | 99国产在线视频 | 日本不卡一区二区 | 中文字幕在线有码 | 日韩av看片 | 狠狠成人 | 国产女做a爱免费视频 | 69亚洲精品 | 国产精品午夜免费福利视频 | 制服丝袜一区二区 | a黄色大片 | www.香蕉视频在线观看 | 日韩精品一区二区三区免费视频观看 | 亚洲激情精品 | 久操视频在线免费看 | 色综合久久综合 | 欧美淫视频 | 亚洲情影院| 国产一区二区三区免费观看视频 | 日韩一二三区不卡 | 美女网色 | 免费网站观看www在线观看 | 97碰在线 | 超碰国产97 | 久久99久久久久 | 欧美日韩国产精品一区二区三区 | 久久免费中文视频 | 亚洲欧美日本国产 | 精品电影一区 | 成人免费网站在线观看 | 在线观看日本高清mv视频 | 国产一区在线免费 | 国产在线观看免费 | 美女免费电影 | 欧美一级片免费播放 | 99久免费精品视频在线观看 | 国产精品原创av片国产免费 | 久久久久国产a免费观看rela | 日韩欧美xxx | 国产精品久久久久一区二区三区 | 欧美精品一区二区蜜臀亚洲 | 天天爽天天做 | 久久久久国产视频 | 久久国产精品免费一区 | 亚洲 欧洲 国产 精品 | 天天做夜夜做 | 亚洲精品视频国产 | 国产a级精品 | 九色91在线视频 | 国产一级电影网 | 日韩理论在线视频 | 国产一级免费在线 | 国产主播99 | 伊人久久精品久久亚洲一区 | 最近日本字幕mv免费观看在线 | 中文字幕在线影视资源 | 亚洲精品视频免费在线 | 亚洲电影影音先锋 | 精品人人人人 | 婷婷色资源 | 国产美女视频网站 | www.com久久| 狠狠狠色丁香综合久久天下网 | 日本韩国精品在线 | 中文字幕中文字幕在线中文字幕三区 | 91香蕉嫩草 | 亚洲精品va| 一区二区三区精品在线视频 | 久久久成人精品 | 欧美日韩亚洲第一 | 中文字幕影片免费在线观看 | 欧美一级在线看 | 免费看一级黄色大全 | 久久国产精品偷 | 久久亚洲福利视频 | 久久精品视频18 | 亚洲国产成人在线观看 | 水蜜桃亚洲一二三四在线 | 中文字幕av免费观看 | 久久99热这里只有精品 | 在线观看av中文字幕 | 日韩在线欧美在线 | 国产精品久久久久四虎 | 一区二区激情视频 | 人人爱爱人人 | 91av观看| 国产在线1区 | 黄色h在线观看 | 久久久人人人 | 在线免费性生活片 | 欧美日韩国产综合网 | 成人午夜av电影 | 色综合久久88色综合天天 | 福利视频精品 | 欧美一二在线 | 国精产品999国精产品视频 | 国产精品一级视频 | 日本在线观看黄色 | 国产黄色网 | 狠狠狠色丁香综合久久天下网 | 开心色停停 | 日韩在线在线 | 国产精品视屏 | 国产精品久久久久久久久久久不卡 | 久久精品导航 | 婷婷天天色 | 色九九视频 | 手机在线视频福利 | 91正在播放| 美女精品国产 | 婷婷在线网站 | 国产色视频一区 | 午夜精品视频在线 | 亚洲 综合 专区 | 精品国产乱码久久久久久1区二区 | 国产成人精品女人久久久 | 国产精品女同一区二区三区久久夜 | 久久影院亚洲 | 亚洲九九九在线观看 | 免费av大全 | 免费精品视频在线 | 亚洲激情在线观看 | 玖玖综合网 | 国产极品尤物在线 | 国产成人精品综合久久久久99 | 91人人澡人人爽 | 精品国产欧美 | 亚洲在线视频免费 | 免费久久99精品国产婷婷六月 | 日韩3区 | 成人免费网视频 | 在线视频1卡二卡三卡 | 91精品在线观看入口 | 国产精品久久久久久久午夜 | 成人在线观看av | 久久国产电影 | 亚洲综合五月天 | 国产精品美女久久久久久久 | 狠狠干免费 | 九九热在线视频免费观看 | 91久久人澡人人添人人爽欧美 | 久久久久在线 | 中国美女一级看片 | 免费看黄网站在线 | 日韩电影在线观看中文字幕 | 天天插天天干天天操 | www.午夜 | 亚洲成人av一区二区 | 久久亚洲精品电影 | 日韩欧美网址 | 丝袜一区在线 | 久草在线久 | 热久久免费视频精品 | 天堂网一区二区三区 | 国产成人精品av在线 | 天天天天综合 | 91精品国产网站 | 丁香六月久久综合狠狠色 | 曰韩精品 | 欧美性生爱 | 精品欧美一区二区在线观看 | 欧美成年网站 | 在线观看免费黄色 | 色综合久久久久久久久五月 | 欧美亚洲xxx | 天天综合操 | 欧美黄色高清 | 一区二区三区在线播放 | 综合在线亚洲 | 天天天操天天天干 | 在线观看欧美成人 | 成人免费视频免费观看 | 天天色.com | 久久久久久久久久亚洲精品 | 在线观看91精品国产网站 | 婷婷网址 | 亚洲一区 av | 特级毛片在线 | 久久综合五月天 | 在线一级片| 人人爽人人插 | 日韩欧美高清在线观看 | 91精品婷婷国产综合久久蝌蚪 | 综合久久网 | 久久久精品久久日韩一区综合 | 国产高清亚洲 | 伊人电影天堂 | 免费手机黄色网址 | 日韩偷拍精品 | 免费观看视频的网站 | 有码中文字幕在线观看 | 在线观看黄网站 | 久久另类小说 | 久草在线播放视频 | 麻豆91在线观看 | 91麻豆高清视频 | 手机在线永久免费观看av片 | 亚洲午夜大片 | 国产黄色播放 | 久久av免费 | 国产午夜三级一二三区 | 欧美精品久久久久性色 | 中文字幕在线免费播放 | 九九久久成人 | 五月婷婷视频在线 | 日本在线h| 日韩在线观看视频免费 | 日韩成人免费在线观看 | 欧美韩日精品 | 日韩理论电影网 | 在线观看91久久久久久 | 亚洲免费精品一区二区 | 中文字幕在线播放一区二区 | 久久99电影 | 99re国产视频 | 波多野结衣综合网 | 久久国产精品久久国产精品 | 激情片av| 国产91九色蝌蚪 | 一区av在线播放 | 亚洲精选国产 | 美女网站在线 | 麻豆免费在线视频 | 日日干 天天干 | 天海冀一区二区三区 | 午夜精品三区 | 久久亚洲综合色 | 亚洲国产欧洲综合997久久, | 日韩精品电影在线播放 | 日本最新一区二区三区 | 日本精品一区二区三区在线播放视频 | 国产一区二区日本 | 欧美日韩视频在线观看一区二区 | 久久在线精品 | 精品国内 | 国产精品一区二区吃奶在线观看 | 久久精品视频国产 | 成年人在线看片 | 亚洲精品白浆高清久久久久久 | 色丁香色婷婷 | 天天干夜夜夜操天 | 亚洲va韩国va欧美va精四季 | 免费视频 你懂的 | 日韩伦理片一区二区三区 | 91免费试看 | 国产黄色大全 | 国产视频精品免费 | 精品在线不卡 | 久久久久久久久久福利 | 99精品电影| 亚洲激情在线视频 | 国产精品初高中精品久久 | 国产精品igao视频网入口 | 国产一区在线免费观看 | av电影免费在线看 | 激情综合网在线观看 | 日韩在线激情 | 六月色婷| 女人久久久久 | 人人超碰免费 | 99 精品 在线 | 欧美成人播放 | 最新国产在线观看 | 粉嫩一区二区三区粉嫩91 | 国产+日韩欧美 | 玖草影院 | 伊人五月婷| 91精品国产三级a在线观看 | 欧美电影在线观看 | 91精品一区在线观看 | 国产精久久久 | 亚洲人人精品 | 91av超碰| 色婷婷激情电影 | 日韩精品一区二区电影 | 国产伦精品一区二区三区四区视频 | 国产高清在线免费 | 日韩免费视频播放 | 国产视频在 | 亚洲第一成网站 | 五月综合色婷婷 | av福利在线导航 | 国产视频精品免费 | 亚洲精品久久久蜜桃直播 | 国产一区在线视频播放 | 日本黄网站 | 久草视频99 | 天天操夜夜干 | 久久艹在线观看 | 午夜黄色大片 | 久久国产女人 | 成 人 黄 色 视频播放1 | 免费看黄色大全 | 国产美女免费视频 | 国产一区视频在线观看免费 | 天天操夜操 | 粉嫩aⅴ一区二区三区 | 一色av| 成人a级大片 | www.97视频 | 伊人春色电影网 | 99精品免费久久久久久久久日本 | 亚洲国产mv | 天天射网 | 日本巨乳在线 | 国产精品亚洲视频 | 五月天视频网 | 日本特黄一级片 | 天天色成人网 | 中文字幕一区二区三区久久 | 国产精品午夜久久久久久99热 | 国产中文字幕免费 | 中文在线√天堂 | 午夜成人免费影院 | 精品久久久久久久久久久久久久久久久久 | 99精品久久只有精品 | 婷婷丁香九月 | 香蕉视频色 | 97免费视频在线 | 韩国一区二区av | 久久精品久久综合 | 免费高清av在线看 | 91人人澡人人爽 | 91超级碰| 丁香婷婷综合色啪 | 欧美婷婷色 | 四虎国产精品免费观看视频优播 | 久草视频在线免费播放 | 在线观看视频日韩 | 三三级黄色片之日韩 | 日日夜夜精品网站 | 中文字幕 第二区 | 男女拍拍免费视频 | 成人视屏免费看 | 精品一区中文字幕 | 国产精品18毛片一区二区 | 日韩久久一区 | 欧美日韩在线免费观看 | 国产一级做a爱片久久毛片a | 午夜国产在线观看 | 日韩电影在线看 | 中文字幕中文字幕中文字幕 | 欧美日韩不卡一区二区 | 国产护士hd高朝护士1 | 少妇av网 | 丁香花在线视频观看免费 | 999精品 | 在线观看亚洲国产 | 激情小说久久 | 国产在线播放观看 | 免费看污片| 国产裸体视频网站 | 中文字幕av在线电影 | 国产精品黄色 | 婷婷六月综合亚洲 | 日韩欧美观看 |