1. 程式人生 > >ant全自動更新部署web程式的詳解

ant全自動更新部署web程式的詳解

由於每次部署花費的時間都比較多:要從svn伺服器更新程式碼,修改配置檔案、甚至還要解決檔案衝突,再打包,再上傳到伺服器端(網上不給力),然後還要停掉tomcat應用伺服器,部署好包之後還要重啟應用伺服器。於是就用ant結合svnant外掛寫了一個自動更新部署的ant配置檔案來解決。配置好之後,只需要在伺服器輸入一個簡單的命令:“ant”,就可以實現全自動更新並重新部署web程式了。

示例配置檔案如下:build.xml

<?xml version="1.0"?>
<!-- 從svn更新原始碼,並重新編譯、打包、部署 -->
<project name="auto-deploy" basedir="." default="redeploy">

	<!-- 屬性定義(在不同的環境,應該要重新定義合適自己的屬性值) -->
	
	<!-- 定義存放檢出程式碼的目錄 -->	
	<property name="checkout_dir" value="project1"/>
	<!-- 指明要檢出的程式碼在svn伺服器上的url -->	
	<property name="project_svn_url" value="https://xxx.com/svn/01 Code/project1/"/>
	<!-- 指明svn賬號 -->	
	<property name="svn_repository_user" value="user1"/>
	<!-- 指明svn密碼 -->	
	<property name="svn_repository_passwd" value="123456789"/>
	<!-- 指明tomcat的目錄 -->
	<property name="tomcat_home" value="F:/company1/apache-tomcat-7.0.47"/>
	<!-- 指定打包後war檔案的名稱 -->
	<property name="war_name" value="project1"/>
	<!-- 指明svnant任務外掛用到的jar檔案的路徑 -->
	<property name="svnant_lib" value="lib"/>
	<!-- 指明編譯時需要用到的其他jar檔案的路徑 -->
	<property name="other_lib" value="3rd_lib"/>

	<!-- 當前時間及格式 -->
	<tstamp>
		<format property="current_time" pattern="yyyyMMddhhmm" locale="zh"/>
	</tstamp>

	<!-- path to the svnant libraries. Usually they will be located in ANT_HOME/lib -->
	<path id="svnant_classpath">
		<fileset dir="${svnant_lib}">
			<include name="**/*.jar"/>
		</fileset>
	</path>  
	<!-- 專案的classpath路徑 -->
	<path id="project_classpath">
		<fileset dir="${checkout_dir}/WebRoot/WEB-INF/lib/"> 
			<include name="*.jar"/>
		</fileset>
		<!-- 編譯時額外需要javax.servlet.jar和javax.servlet.jsp.jar -->
		<fileset dir="${other_lib}">
			<include name="*.jar"/>
		</fileset>
	</path> 

	<!-- 引入svn任務 -->
	<typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="svnant_classpath" />
	<!-- 設定svn屬性 -->
	<svnSetting id="svnparams" username="${svn_repository_user}" password="${svn_repository_passwd}" javahl="false"/> 

	<!-- 刪除原始碼資料夾 -->
	<target name="clean-src">
		<echo message="開始刪除檢出的原始碼(原始碼目錄:${checkout_dir}),請稍後..." />
		<delete dir="${checkout_dir}"/>
		<echo message="原始碼刪除完畢。" />
	</target>

	<!-- 從SVN伺服器checkout原始碼 -->
	<target name="checkout" depends="clean-src">
		<echo message="開始從svn伺服器${project_svn_url}檢出程式碼,請稍後..." /> 
		<svn refid="svnparams">
			<checkout url="${project_svn_url}" revision="HEAD" destPath="${checkout_dir}"  force="true"/>
		</svn>
		<echo message="從svn伺服器${project_svn_url}檢出程式碼完成。" />
	</target>
	
	<!-- 從SVN伺服器update原始碼 -->
	<target name="update">
		<echo message="開始從svn伺服器${project_svn_url}更新程式碼,請稍後..." />
			<update revision="HEAD" dir="${checkout_dir}" />
		<echo message="從svn伺服器${project_svn_url}更新程式碼完成。" />
	</target>

		<!-- 清除舊的編譯檔案 -->
	<target name="clean-class">
	<echo message="開始清空classes資料夾內之前編譯生成的舊的類檔案,請稍後..." />
		<delete dir="${checkout_dir}/WebRoot/WEB-INF/classes"/>
		<mkdir dir="${checkout_dir}/WebRoot/WEB-INF/classes"/>
		<echo message="classes檔案清空完畢。" />

	</target>
	
	<!-- 編譯原始碼 -->
	<target name="compile" depends="checkout,clean-class">
		<echo message="開始編譯原始檔,請稍後..." /> 
		<javac nowarn="true" destdir="${checkout_dir}/WebRoot/WEB-INF/classes" source="1.5" target="1.5" debug="false"  
                  deprecation="false" optimize="false" failonerror="true">  
			<src path="${checkout_dir}/src"/>
			<classpath refid="project_classpath"/>
		</javac>  
	</target> 

	<!-- 複製配置檔案 -->
	<target name="copy-config-files" depends="compile">
		<copy todir="${checkout_dir}/WebRoot/WEB-INF/classes/conf/">  
			<fileset dir="${checkout_dir}/src/conf/"/>
		</copy>
		<copy todir="${checkout_dir}/WebRoot/WEB-INF/classes/">  
			<fileset file="${checkout_dir}/src/log4j.properties"/>
		</copy>  		
	</target> 

	<!-- 生成war包 -->
	<target name="generate-war" depends="copy-config-files">
		<war warfile="./${war_name}.war" webxml="${checkout_dir}/WebRoot/WEB-INF/web.xml" excludes="*.svn">
			<lib dir="${checkout_dir}/WebRoot/WEB-INF/lib"/>
			<classes dir = "${checkout_dir}/WebRoot/WEB-INF/classes"/>
			<fileset dir="${checkout_dir}/WebRoot"/>
		</war>
	</target>

	<!-- 啟動tomcat -->
	<target name="start-tomcat">
		<echo>開始啟動tomcat,請稍後....</echo>
		<exec executable="${tomcat_home}/bin/startup.bat"  failonerror="false" 
					 vmlauncher="false"  output="${tomcat_home}/logs/log.txt" append="true">
			<!-- <arg value="/c" /> -->  
			<env key="CATALINA_HOME" path="${tomcat_home}"/>
			<arg value="/c startup.bat" />   
		</exec>
		<!-- 檢測tomcat的URL是否可以訪問成功,訪問成功則認為tomcat啟動完成 -->
		<waitfor maxwait="10" maxwaitunit="minute"  checkevery="1000">
			<http url="http://localhost:8080/"/>
		</waitfor>
		<echo>啟動tomcat完成。</echo>
	</target>

	<!-- 停止tomcat,生成war檔案成功才停止tomcat來部署 -->
	<target name="stop-tomcat" depends="generate-war">  
		<echo>開始停止tomcat,請稍後...</echo>  
		<exec executable="${tomcat_home}/bin/shutdown.bat"  failonerror="false"   
                    output="${tomcat_home}/logs/log.txt" append="true" >  
			<!-- <arg value="/c" /> -->     
			<env key="CATALINA_HOME" path="${tomcat_home}"/>  
			<arg value="/c shutdown.bat" />     
		</exec>
		<!-- 檢測tomcat的URL是否訪問失敗(用not標籤),訪問失敗則認為tomcat已經停止。 -->
		<waitfor maxwait="10" maxwaitunit="minute"  checkevery="1000">
			<not>
				<http url="http://localhost:8080/"/>
			</not>
		</waitfor>
		<echo>停止tomcat完成。</echo>
	</target> 

	<!-- 檢查是否存在已經部署的舊的目標war包。 -->
	<target name="old-war-exist-check"> 
		<echo>檢查是否存在舊的同名war檔案...</echo>
		<available file="${tomcat_home}/webapps/${war_name}.war"  property="old-war-isexist"/>
	</target>

	<!-- 重新部署前,備份原來的war檔案。 -->
	<target name="backup-old-war" depends="old-war-exist-check"  if="old-war-isexist">

		<echo>存在舊的同名war檔案,開始備份之前部署的舊的同名war檔案...</echo>
		<copy tofile="./${war_name}_bak${current_time}.war">  
			<fileset file="${tomcat_home}/webapps/${war_name}.war"/>
		</copy> 
		<echo>備份舊的同名war檔案完畢。</echo>
	</target>		

	<!-- 刪除原來的war檔案 -->
	<target name="delete-old-war" depends="backup-old-war" if="old-war-isexist">
		<echo>開始刪除舊的同名war檔案...</echo>
		<delete file="${tomcat_home}/webapps/${war_name}.war"/>		 
		<echo>刪除舊的同名war檔案完畢。</echo>
	</target>



	<!-- 檢查是否存在已經部署的目標context資料夾。 -->
	<target name="old-context-exist-check"> 
		<echo>檢查是否存在舊的同名context資料夾...</echo>
		<available file="${tomcat_home}/webapps/${war_name}" type="dir"  property="old-context-isexist"/>
	</target>

	<!-- 刪除舊的目標context資料夾 -->
	<target name="delete-old-context" depends="old-context-exist-check" if="old-context-isexist">
		<echo>存在舊的同名context資料夾,開始刪除舊的同名context資料夾...</echo>
		<delete dir="${tomcat_home}/webapps/${war_name}"/> 
		<echo>刪除舊的同名context資料夾完畢。</echo>
	</target>



	<!-- 把新打包的war檔案複製到tomcat的webapps目錄下 -->
	<target name="copy-new-war-into-webapps" depends="delete-old-context,delete-old-war">
		<echo>開始複製新的war檔案到tomcat的webapps目錄下,請稍後...</echo>
		<copy tofile="${tomcat_home}/webapps/${war_name}.war">  
			<fileset file="./${war_name}.war"/>
		</copy> 		 
		<echo>複製新的war檔案到tomcat的webapps目錄下完畢。</echo>
	</target>
	
	
	<!-- 部署,主要是執行依賴任務 -->
	<target name="redeploy" depends="stop-tomcat,copy-new-war-into-webapps,start-tomcat">
		<echo>部署完畢,請測試是否部署成功。</echo>
	</target>
	
</project>

此外注意幾點:

1、已經配置好Ant的環境變數。


2、從svn上更新下來的配置檔案(例如配置資料庫的db.properties)可能會被其他人修改,為了保證配置檔案的正確性,最好是自己準備一份正確的配置檔案,等專案checkout完畢後,用自己的配置檔案覆蓋掉從svn上更新下來的配置檔案。


3、目前的配置是每次都從svn伺服器上checkout或export整個專案,這會浪費很多時間,svnant配置update的沒配置成功,還要繼續研究。

4、這是自己第一次寫ant的配置檔案,可能寫得不太合理,應該還有很多改進的空間。