???????????????????????????? Tomcat5.5.16 部署web項目源碼詳解
Tomcat.5.5.16 安裝 web 項目時執行的代碼主要是 HostConfig 類,其中 deployApps() 執行部署 web 應用的功能;
protected void deployApps() {
?
??????? File appBase = appBase();
??????? File configBase = configBase();
??????? // Deploy XML descriptors from configBase
???? ???deployDescriptors(configBase, configBase.list());
??????? // Deploy WARs, and loop if additional descriptors are found
??????? deployWARs(appBase, appBase.list());
??????? // Deploy expanded folders
??????? deployDirectories(appBase, appBase.list());
? ??????
??? }?
從上面這段代碼,我們可以知道 tomcat 在部署 web 項目是按如下順序依次部署的;
1.??? 首先部署 $CATALINA_HOME/conf/Catalina/localhost 目錄下面的 .xml 文件;
deployDescriptors(configBase, configBase.list());
(1)????? configBase 的值是通過調用 configBase() 獲取的,
?? ??File file = new File(System.getProperty("catalina.base"), "conf");
??? ????Container parent = host.getParent();
??????? if ((parent != null) && (parent instanceof Engine)) {
??????????? file = new File(file, parent.getName());
??????? }
file = new File(file, host.getName());
可以看出 configBase 是由四部分內容組成 ;
System.getProperty("catalina.base") + “conf” + parent.getName()+host.getName()
parent.getName() 和 host.getName() 是分別取 server.xml 中
<Engine name="Catalina" defaultHost="localhost"> 和
<Host name="localhost" appBase="webapps"? … 對應的 name 屬性值;
由此可以得出 configBase 的值為 $CATALINA_HOME/conf/Catalina/localhost
?
??????? (2) 按文件名順序依次讀取 configBase 目錄下面的 xml 文件部署 web 應用;
??????? ??? 第一步,首先獲取文件名(不包含 .xml )作為上下文路徑
????????????? ??String nameTmp = files[i].substring(0, files[i].length() - 4);
??????????????? String contextPath = "/" + nameTmp.replace('#', '/');
????? ????? 第二步,解析 xml 文件,分析 docBase 的值;
??? 注意這里的 docBase 的判斷很重要,采用和以前版本完全不同的做法;
? ???????????????????????????????? ?if (!docBase.isAbsolute()) {
??????????????????? ????docBase = new File(appBase(), context.getDocBase());
?????????????? ????? ?}
????????????????? 首先判斷 docBase 是否為絕對路徑,如果不是絕對路徑,在改為
???? ????????????????? $CATALINA_HOME/webapps+docBase
??
??????????????? ?????// If external docBase, register .xml as redeploy first
?????????????? ???? ?if(!docBase.getCanonicalPath().startsWith(appBase().getAbsolutePath()))
{
// 這個判斷很重要,這里是判斷如果 docBase 路徑是以
$ CATALINA_HOME/webapps+docBase 開頭的字符串,則忽略掉了
??????????????????? ????? ?isExternal = true;
??????????????????? ?????? ...
??????????????????? ???if (docBase.getAbsolutePath().toLowerCase().endsWith(".war")) {
??????????? ???????????? ????isWar = true;
??????????????????? ???}
??????????????? ???} else{
?????? // Ignore specified docBase
???? context.setDocBase(null);
}
??????????
????????? 從上面可以看出, <Context path="/xxxx" docBase="xxxx" . 中 docBase 只有為絕對路徑并且該路徑不是以 $CATALINA_HOME/webapps 開頭,才會生效;否則就忽略掉了;
?
?
2.??? 接下來部署 $CATALINA_HOME/webapps/ 目錄下以。 War 結尾的文件
deployWARs(appBase, appBase.list());
(1) 首先仍是把文件名 ( 不用 .war) 作為其應用的上下文路徑 ;
? ? ?if (files[i].toLowerCase().endsWith(".war")) {
??????????????? // Calculate the context path and make sure it is unique
??????????????? String contextPath = "/" + files[i];
??????????????? int period = contextPath.lastIndexOf(".");
??????? (2) 接下來判斷以該上下文路徑 contextPath 是否已經裝載過了,如果是則直接退出; ?? ?if (deploymentExists(contextPath))
??????????? ?????????return;
?????? ( 3 ) 繼續判斷以該上下文命名的部署文件是否存在,如 war 文件為 AAA.war, 則判斷在 $CATALINA_HOME/conf/Catalina/localhost/AAA.xml 文件是否存在,如果不存在繼續執行以下操作;
????????? ? ?File xml = new File
??????????? (configBase, file.substring(0, file.lastIndexOf(".")) + ".xml");
??????? if (deployXML && !xml.exists()) {
????????? entry = jar.getJarEntry(Constants.ApplicationContextXml);
????????? configBase.mkdirs();
????????? 。。。
????? 先從 wart 文件中讀取 META-INF/context.xml 文件,然后把它 copy 到
????? $CATALINA_HOME/conf/Catalina/localhost/AAA.xml, 注意 war 文件部署文件必須為
context.xml ,且在 META-INF 目錄下; ??
? ( 4 )接下來操作和上面類似,部署該 web 應用;
3. 最后是以 $CATALINA_HOME/webapps 目錄下的文件夾為目標按文件夾名順序進行部署;
? ? ?deployDirectories(appBase, appBase.list());
(1)?????? 同樣先把該文件夾名作為上下文路徑進行部署;
???????? ? ??File dir = new File(appBase, files[i]);
??????????? if (dir.isDirectory()) {
?
??????????????? // Calculate the context path and make sure it is unique
??????????????? String contextPath = "/" + files[i];
?????????????
(2)?????? 接下來的步驟就基本上是一樣了,首先判斷該上下文路徑是否已經部署過,如果是則直接退出,否則和上面一樣,讀取 META-INF/context.xml 文件進行部署;
注意這里和上面的 war 文件部署稍微有點不同,就是它不會 copy 部署文件 context.xml 文件到 $CATALINA_HOME/conf/Catalina/localhost 中去;
?
?
?
我的應用放在
/tomcat6/myWeb/test1234,端口為1234
此時 docBase="test1234"
http://127.0.0.1:1234
http://127.0.0.1:1234/test1234均可直接訪問
去掉 docBase后,只有
http://127.0.0.1:1234/test1234