1. 需要準(zhǔn)備好下面這些工具
JDK 1.6+
Maven 2或3
TortoiseSVN 1.7+ (從1.7開(kāi)始”.svn”目錄集中放在一處了,不再每個(gè)目錄下都放一份)
Eclipse 3.5+
這4個(gè)工具不在這里描述怎么配置了,如果你是有兩三年開(kāi)發(fā)經(jīng)驗(yàn)的Java開(kāi)發(fā)人員,正常來(lái)講都一直在用了。
另外,分析tomcat源代碼不需要對(duì)這4個(gè)工具做什么特殊配置。
2. 下載Tomcat的源代碼
Apache旗下的開(kāi)源項(xiàng)目基本上都放在這: http://svn.apache.org/repos/asf
里面包含了tomcat、struts、hadoop、hbase等流行的開(kāi)源項(xiàng)目的源代碼,
可以直接用瀏覽器打開(kāi)這個(gè)URL,或者用TortoiseSVN的Repository Browser打開(kāi)它。
tomcat的svn是: http://svn.apache.org/repos/asf/tomcat, 如下圖所示:

目前tomcat有4個(gè)大分支:
5.5 : http://svn.apache.org/repos/asf/tomcat/tc5.5.x
6.0 : http://svn.apache.org/repos/asf/tomcat/tc6.0.x
7.0 : http://svn.apache.org/repos/asf/tomcat/tc7.0.x
8.0 : http://svn.apache.org/repos/asf/tomcat/trunk
5.5分支會(huì)在今年9月30號(hào)后停止維護(hù),所以除非有歷史遺留系統(tǒng),不推薦再去讀它的代碼,
6.0分支是比較成熟的,在生產(chǎn)環(huán)境用得比較多,
目前官方對(duì)這個(gè)分支進(jìn)入維護(hù)、bugfix階段,很少有新功能添加進(jìn)來(lái)了,
我個(gè)人也不推薦讀它的代碼,代碼相對(duì)7.0來(lái)講比較臟亂。
7.0分支完整實(shí)現(xiàn)了servlet 3.0規(guī)范,已陸續(xù)發(fā)布了27個(gè)小版本,己經(jīng)穩(wěn)定了,可用于生產(chǎn)環(huán)境,
代碼比5.5、6.0分支干凈整潔得多,這也是我強(qiáng)烈向你推薦的版本。
8.0分支主要關(guān)注web socket和spdy,正處于活躍開(kāi)發(fā)階段,代碼變動(dòng)比較頻繁,保持關(guān)注即可。
所以這篇文章講的是7.0分支,研究tomcat推薦直接提取svn的源代碼:
用TortoiseSVN checkout這個(gè)svn的代碼:http://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk
放到D:\Tomcat7\trunk (你可以換別的目錄)
然后再?gòu)倪@下載一個(gè)二進(jìn)制分發(fā)包(Binary Distributions)
http://labs.mop.com/apache-mirror/tomcat/tomcat-7/v7.0.27/bin/apache-tomcat-7.0.27.zip
解壓后放到D:\Tomcat7,順便把”apache-tomcat-7.0.27″重命名成launch吧,
用這個(gè)二進(jìn)制分發(fā)包而不是從源代碼構(gòu)建只是為了節(jié)省時(shí)間,
直接用它c(diǎn)onf目錄里面的配置文件和webapps下的例子。
3. 把它變成maven工程
主要是添加幾個(gè)依賴(lài)(ecj、ant、jaxrpc等),否則的話(huà)導(dǎo)入eclipse后會(huì)有編譯錯(cuò)誤,
另外,因?yàn)閠omcat不是標(biāo)準(zhǔn)的maven工程項(xiàng)目,比如沒(méi)有src\main\java這樣的目錄,
所以要調(diào)整一下sourceDirectory和testSourceDirectory,下面是一個(gè)完整的pom文件,
直接放到D:\Tomcat7目錄即可(pom.xml與之前的launch、trunk目錄并列)
(注: pom.xml文件在附件中)
Xml代碼

- <project xmlns=“http://maven.apache.org/POM/4.0.0″ xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
- xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd”>
- <modelVersion>4.0.0</modelVersion>
-
- <groupId>org.apache.tomcat</groupId>
- <artifactId>Tomcat7.0</artifactId>
- <name>Tomcat7.0</name>
- <version>7.0</version>
-
- <build>
- <finalName>Tomcat7.0</finalName>
- <sourceDirectory>trunk/java</sourceDirectory>
- <testSourceDirectory>trunk/test</testSourceDirectory>
- <resources>
- <resource>
- <directory>trunk/java</directory>
- </resource>
- </resources>
- <testResources>
- <testResource>
- <directory>trunk/test</directory>
- </testResource>
- </testResources>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>2.3</version>
- <configuration>
- <source>1.6</source>
- <target>1.6</target>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.4</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jdt.core.compiler</groupId>
- <artifactId>ecj</artifactId>
- <version>3.7.2</version>
- </dependency>
- <dependency>
- <groupId>ant</groupId>
- <artifactId>ant</artifactId>
- <version>1.7.0</version>
- </dependency>
- <dependency>
- <groupId>wsdl4j</groupId>
- <artifactId>wsdl4j</artifactId>
- <version>1.6.2</version>
- </dependency>
- <dependency>
- <groupId>javax.xml</groupId>
- <artifactId>jaxrpc</artifactId>
- <version>1.1</version>
- </dependency>
- </dependencies>
-
- </project>
4. 導(dǎo)入Eclipse
在命令行窗口中進(jìn)入D:\Tomcat7目錄,執(zhí)行 mvn eclipse:eclipse 就可以轉(zhuǎn)成eclipse工程項(xiàng)目了,
然后打開(kāi)eclipse,點(diǎn)”File->Import->General->Existing Projects into Workspace”,
最后打開(kāi)D:\Tomcat7就能看到Tomcat7.0這個(gè)項(xiàng)目了。
(如果eclipse裝了m2e插件不用執(zhí)行mvn eclipse:eclipse的,可以直接導(dǎo)入maven工程)
5. 在Eclipse中讓Tomcat跑起來(lái)
在Eclipse中打開(kāi)org.apache.catalina.startup.Bootstrap類(lèi),
在編輯區(qū)右擊,點(diǎn)”Run As->Run configurations”,然后雙擊”Java Aplication”就會(huì)出來(lái)一個(gè)新的”Bootstrap”,
選中它,在右邊點(diǎn)擊”Arguments”那一欄,把下面的內(nèi)容copy到”VM arguments”中:
-Dcatalina.home=launch -Dcatalina.base=launch -Djava.endorsed.dirs=launch/endorsed -Djava.io.tmpdir=launch/temp -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=launch/conf/logging.properties
如下圖:

然后點(diǎn)run按鈕,就可以啟動(dòng)tomcat了,啟動(dòng)成功會(huì)在Eclipse的console中顯示:
- 2012-6-10 14:25:31 org.apache.catalina.startup.Catalina start
- 信息: Server startup in 359 ms
除上面這種方式外,這里還有一個(gè)Eclipse的launch腳本(start-tomcat7.launch (注: 在附件中)),
- <?xml version=“1.0″ encoding=“UTF-8″ standalone=“no”?>
- <launchConfiguration type=“org.eclipse.jdt.launching.localJavaApplication”>
- <listAttribute key=“org.eclipse.debug.core.MAPPED_RESOURCE_PATHS”>
- <listEntry value=“/Tomcat7.0/trunk/java/org/apache/catalina/startup/Bootstrap.java”/>
- </listAttribute>
- <listAttribute key=“org.eclipse.debug.core.MAPPED_RESOURCE_TYPES”>
- <listEntry value=“1″/>
- </listAttribute>
- <stringAttribute key=“org.eclipse.jdt.launching.MAIN_TYPE” value=“org.apache.catalina.startup.Bootstrap”/>
- <stringAttribute key=“org.eclipse.jdt.launching.PROGRAM_ARGUMENTS” value=“start”/>
- <stringAttribute key=“org.eclipse.jdt.launching.PROJECT_ATTR” value=“Tomcat7.0″/>
- <stringAttribute key=“org.eclipse.jdt.launching.VM_ARGUMENTS” value=“-Dcatalina.home=launch -Dcatalina.base=launch -Djava.endorsed.dirs=launch/endorsed -Djava.io.tmpdir=launch/temp -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=launch/conf/logging.properties”/>
- </launchConfiguration>
可以放到D:\Tomcat7目錄,然后flush一下Eclipse,在Eclipse中右擊這個(gè)文件,點(diǎn)Run As啟動(dòng)Tomcat,點(diǎn)Debug As可以調(diào)試Tomcat。
下圖是Tomcat在Eclipse中的項(xiàng)目布局:

最后,打開(kāi)你的瀏覽器,輸入 http://127.0.0.1:8080/examples/ 看看例子吧。
6. 簡(jiǎn)單的源代碼閱讀指南:
- 包名 用途
- =================================================
- javax servlet/jsp/el相關(guān)的api
- org.apache.catalina tomcat自身架構(gòu)
- org.apache.coyote http、ajp協(xié)議實(shí)現(xiàn)相關(guān)的類(lèi)
- org.apache.el 實(shí)現(xiàn)el規(guī)范
- org.apache.jasper 實(shí)現(xiàn)jsp規(guī)范、編譯jsp文件
- org.apache.juli tomcat的日志系統(tǒng)
- org.apache.naming jndi實(shí)現(xiàn)
- org.apache.tomcat tomcat的工具包、net、digester xml解析器
閱讀順序:
可以從org.apache.catalina.startup.Bootstrap這個(gè)類(lèi)開(kāi)始看起,
然后到org.apache.catalina.startup.Catalina,
在Catalina類(lèi)中會(huì)觸發(fā)conf/server.xml文件的解析,
這時(shí)要看org.apache.tomcat.util.digester中的類(lèi),
解析的過(guò)程中會(huì)用到org.apache.catalina.startup包中的很多RuleSet類(lèi),
server.xml文件解析完后,會(huì)生成org.apache.catalina.core包中的各種StandardXXX類(lèi)的實(shí)例,
比如StandardServer、StandardService、StandardEngine等等,
這些Standard組件都是有生命周期的,接著會(huì)調(diào)用他們的init、start等方法,
會(huì)觸發(fā)下面這些組件進(jìn)入init、start狀態(tài)
org.apache.catalina.connector.Connector
org.apache.coyote.http11.Http11Protocol
org.apache.tomcat.util.net.JIoEndpoint
在JIoEndpoint(或NioEndpoint、AprEndpoint)中會(huì)監(jiān)聽(tīng)8080這樣的端口,
有請(qǐng)求進(jìn)來(lái)了,就進(jìn)行相關(guān)的io操作,接著轉(zhuǎn)到org.apache.coyote包中的相應(yīng)類(lèi)進(jìn)行協(xié)議解析,
生成org.apache.catalina.connector.Request和org.apache.catalina.connector.Response實(shí)例,
然后轉(zhuǎn)到各種Valve、應(yīng)用Filter,最后到達(dá)應(yīng)用的Servlet/JSP。
下圖描述了Tomcat7的核心架構(gòu):
