之前沒有仔細研究這個問題,學的時候别人說Servlet執行個體是在web container啟動時也即是伺服器啟動過程就new 出來。某個Servlet執行個體一旦new 出來,馬上就會執行其init(ServletConfig sc)方法。
上面這句話,前半句是錯了,後半句是正确的,這個直到今天我才發現。哇,這麼久了,現在才發現這個錯誤,對自己感到一絲悲哀啊。。好,廢話不多說,先看我做的實驗,然後再分析哈源碼。
實驗一
準備Servlet:
package com.eabax.web.action.product;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public class ServletTest extends HttpServlet {
public ServletTest() {
System.out.println("*****************************************************");
System.out.println("new instance of class ServletTest");
System.out.println("*****************************************************");
}
public void init() throws ServletException {
super.init();
System.out.println("*****************************************************");
System.out.println("call Servlet init method");
System.out.println("*****************************************************");
}
}
配置web.xml:
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>com.eabax.web.action.product.ServletTest</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>*.php</url-pattern>
</servlet-mapping>
部署web應用,并啟動tomcat server 6.0.36,輸出如下:
Jan 12, 2014 11:28:15 AM org.apache.catalina.core.AprLifecycleListener init
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: D:\Program Files\Java\jdk1.7.0_45\bin;E:\Installation Programs\About Java\Java tools\Tomcat server\apache-tomcat-6.0.36\bin
Jan 12, 2014 11:28:16 AM org.apache.coyote.http11.Http11Protocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
Jan 12, 2014 11:28:16 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 1069 ms
Jan 12, 2014 11:28:16 AM org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
Jan 12, 2014 11:28:16 AM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.36
Jan 12, 2014 11:28:16 AM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor host-manager.xml
Jan 12, 2014 11:28:16 AM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor manager.xml
Jan 12, 2014 11:28:16 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory CqutSecondHandTradeSystem
log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Jan 12, 2014 11:28:18 AM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Jan 12, 2014 11:28:25 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory docs
Jan 12, 2014 11:28:25 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory jpa_test
Jan 12, 2014 11:28:25 AM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(E:\Installation Programs\About Java\Java tools\Tomcat server\apache-tomcat-6.0.36\webapps\jpa_test\WEB-INF\lib\servlet-api.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
Jan 12, 2014 11:28:26 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory ROOT
Jan 12, 2014 11:28:26 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory tag
Jan 12, 2014 11:28:26 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory user
Jan 12, 2014 11:28:26 AM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory xhEditor
Jan 12, 2014 11:28:27 AM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Jan 12, 2014 11:28:27 AM org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
Jan 12, 2014 11:28:27 AM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/44 config=null
Jan 12, 2014 11:28:27 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 11329 ms
從Tomcat的啟動日志資訊中可以發現,并沒有輸出類ServletTest的的初始化代碼,也就是Tomcat啟動過程中并沒有new 出Servlet的執行個體。
下面從浏覽器中通路位址:
http://localhost:8080/jpa_test/aaa.php,控制台輸出如下:
Jan 12, 2014 11:28:27 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 11329 ms
*****************************************************
new instance of class ServletTest
*****************************************************
*****************************************************
call Servlet init method
*****************************************************
從以上過程中,就可以發現:Servet執行個體的初始化時刻并非是web container啟動的時候,而是第一次需要該Servlet處理請求的時候。
實驗二
與實驗一唯一不同的地方就是這次實驗在web.xml檔案中register servlet的時侯,多加了一個load-on-startup參數。如下:
<servlet>
<servlet-name>test</servlet-name>
<servlet-class>com.eabax.web.action.product.ServletTest</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>test</servlet-name>
<url-pattern>*.php</url-pattern>
</servlet-mapping>
Jan 13, 2014 6:12:45 PM org.apache.catalina.core.AprLifecycleListener init
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: D:\Program Files\Java\jdk1.7.0_45\bin;E:\Installation Programs\About Java\Java tools\Tomcat server\apache-tomcat-6.0.36\bin
Jan 13, 2014 6:12:45 PM org.apache.coyote.http11.Http11Protocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
Jan 13, 2014 6:12:45 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 960 ms
Jan 13, 2014 6:12:45 PM org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
Jan 13, 2014 6:12:45 PM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.36
Jan 13, 2014 6:12:45 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor host-manager.xml
Jan 13, 2014 6:12:46 PM org.apache.catalina.startup.HostConfig deployDescriptor
INFO: Deploying configuration descriptor manager.xml
Jan 13, 2014 6:12:46 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory CqutSecondHandTradeSystem
log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Jan 13, 2014 6:12:47 PM org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
Jan 13, 2014 6:12:54 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory docs
Jan 13, 2014 6:12:54 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory jpa_test
Jan 13, 2014 6:12:54 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(E:\Installation Programs\About Java\Java tools\Tomcat server\apache-tomcat-6.0.36\webapps\jpa_test\WEB-INF\lib\servlet-api.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
*****************************************************
new instance of class ServletTest
*****************************************************
*****************************************************
call Servlet init method
*****************************************************
Jan 13, 2014 6:12:55 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory ROOT
Jan 13, 2014 6:12:55 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory tag
Jan 13, 2014 6:12:55 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory user
Jan 13, 2014 6:12:55 PM org.apache.catalina.startup.HostConfig deployDirectory
INFO: Deploying web application directory xhEditor
Jan 13, 2014 6:12:55 PM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Jan 13, 2014 6:12:55 PM org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
Jan 13, 2014 6:12:55 PM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/22 config=null
Jan 13, 2014 6:12:55 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 10284 ms
從以上輸出資訊可見,這次tomcat在啟動過程中new 出了Servlet的執行個體。通過上面兩個實驗也可以知道在register Servlet的時候,加了load-on-startup和沒有加這個參數的差別了。
源碼分析
做到這裡,才發現分析源碼就得分析Tomcat的源碼,這超出了我之前的預料。于是我把Tomcat的jar包也導入工程,并attach source,試圖分析源碼。但是其真的很複雜,還不能做到從tomcat入口開始分析,一步一步分析程式的執行過程。是以萌生了調試tomcat的想法。于是經過查找資料,整理出了在myeclipse2013種調試tomcat的步驟。有興趣的coder可以參考另一篇博文:
MyEclipse中調試Tomcat,歡迎吐槽。