<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-57  評論-117  文章-1  trackbacks-0

    副標(biāo)題:利用ant腳本 自動構(gòu)建svn增量/全量 系統(tǒng)程序升級包

    首先請允許我這樣說,作為開發(fā)或測試,你一定要具備這種本領(lǐng)。你可以手動打包、部署你的工程,但這不是最好的方法。最好的方式就是全自動化的方式。開發(fā)人員提交了代碼后,可以自動構(gòu)建、打包、部署到測試環(huán)境。測試通過后進(jìn)入到模擬環(huán)境或是直接發(fā)布的生產(chǎn)環(huán)境,這個過程可以是全自動的。但這個自動化的方式有一些公司用到了,但也有很多公司還不知道,他們的攻城師天天在做反復(fù)、沒有多大意義的、浪費生命的事情。當(dāng)然這種方式一般針對做自己的產(chǎn)品,如電商、通信行業(yè)。而給其他公司或企業(yè)做項目的比較少利用這種方式,當(dāng)然也可以利用這種方式,只是不能直接發(fā)布到客戶的服務(wù)器而已。當(dāng)然有些公司是專門有人做這部分事情的!

    說了這么多也沒有什么惡意,只是覺得這種方式可以大大提高效率,降低人力、物力、財力而已。勿噴,O(∩_∩)O哈哈~嘿嘿~

    在部署項目或打包項目中,通常大家都是手動部署或打包的多。很多公司把這一任務(wù)交個了我們做開發(fā)的,其實這部分應(yīng)該誰做呢?本質(zhì)上應(yīng)該是測試的來完成,但一些公司的測試不會做這個,慢慢的就變成了開發(fā)的事情。有些公司是人手比較少、不健全,所以一部分人自己承擔(dān)了這個事情。在我們手動打包的時,其實這是一個重復(fù)的、沒有技術(shù)含量的、耗費體力的活兒。一般步驟就是更新svn上代碼、修改好相關(guān)的配置、編譯class、發(fā)布到tomcat(web工程)、測試啟動無誤、手動打包。

    而有一種比較簡單快速的方式就是利用meven或ant來完成這些工作,只要我們編寫好腳本后。給相關(guān)的工作人員去運(yùn)行這部分腳本就可以完成打包,甚至是部署項目,這些都是so easy~!我個人也比較贊成使用這種方式,比較簡單、快速、重用性好,最難的可能編寫build腳本,但這個腳本其實也是很簡單的,它就想dos命令行,只不過它是用xml方式來完成命令行的而已。所以測試會寫ant的build腳本這個也是應(yīng)該的,如果你不會的話,還是建議你學(xué)習(xí)學(xué)習(xí)。反正是百益無一害的事情,何樂而不為呢!

     

    一、基本流程

    利用ant打包項目或打增量包的基本流程

    image

    值得一提的是jar包這個部分,這個步驟是為下面編譯增量包做準(zhǔn)備的。因為增量包導(dǎo)出的增量文件,它依賴于整個項目的其他代碼,如果沒有這些代碼的支持是編譯不通過。然而又不能直接通過diff得到增量的class,所以只能導(dǎo)出增量文件后,通過引用全部工程的代碼的class再進(jìn)行編譯即可。

     

    二、運(yùn)行環(huán)境

    1、安裝jdk,不會自己上網(wǎng)查其他的

    2、如果你還沒有安裝ant,那么你可以參考:http://www.cnblogs.com/hoojo/archive/2013/06/14/java_ant_project_target_task_run.html

    會介紹一下ant的安裝和使用的方法。

    3、這里需要用到svn的ant相關(guān)工具包、命令支持。你需要下載svnant-1.3.1.zip,將里面的lib庫放置在你的ant腳本的編譯運(yùn)行環(huán)境中。

    4、因為某些項目使用到了泛型、annotation注解,使用javac有些代碼是編譯不通過的,所以這里使用了jdt的編譯方式。參考:使用eclipse JDT compile class 會有很詳細(xì)的介紹。

    需要用到

    jdtCompilerAdapter.jar
    org.eclipse.jdt.compiler.tool_1.0.1.v_793_R33x.jar
    org.eclipse.jdt.core_3.3.3.v_793_R33x.jar
    org.eclipse.jdt.debug.ui_3.2.102.v20071002_r332.jar
    復(fù)制到ant_home/lib目錄下,如果是利用eclipse運(yùn)行腳本就需要把它加載到運(yùn)行環(huán)境中。可以參考上面的:使用eclipse JDT compile class

     

    三、編寫ant的build腳本

    1、首先看看ant工程的目錄結(jié)構(gòu)

    image

    簡單介紹下目錄結(jié)構(gòu):

    src下面的ExportIncrementFiles.java是導(dǎo)出增量文件要用的,它在build命令increment中執(zhí)行。它會讀取diff 比較后的文件中的內(nèi)容,并導(dǎo)出文件

    dest 是checkout出來最新的svn的工程

    dist 是編譯上面dest目錄中的工程,也是svn全量war的工程目錄和jar

    increment_dest 是增量工程,也就是上面的ExportIncrementFiles工具導(dǎo)出的工程

    increment_dist 是編譯上面increment_dest 的工程,也是增量包的工程目錄

    因為每個人的項目工程目錄結(jié)構(gòu)不一樣,所以這個腳本并不會通用,我這里指針對自己的項目進(jìn)行測試。

    lib中是運(yùn)行環(huán)境需要的jar庫,其中主要的就是svnlib 這個你可以去下載 svnant-1.3.1.zip 以及JDT編譯class的jar包,這個可以通過eclipse中的plugin中的jar包找到,可以參考:使用eclipse JDT compile class

    increment.export.jar就是ExportIncrementFiles的class打成的jar包,這個是自己打的包,可以直接應(yīng)用class也可以的,在increment命令引用,jar下載:http://download.csdn.net/detail/ibm_hoojo/6501165

    build.properties是當(dāng)前build的配置文件

    build.xml就是主要的ant腳本

    選中部分是打的war包,這個就可以部署了

    patch.txt就是svn的diff 比較出的增量文件的目錄路徑列表

     

    2、ExportIncrementFiles.java 導(dǎo)出增量文件

    package com.hoo.util;
     
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.FileReader;
     
    /**
     * <b>function:</b> 導(dǎo)出在增量的文件
     * @author hoojo
     * @createDate 2013-11-2 下午10:00:01
     * @file ExportIncrementFiles.java
     * @package com.hoo.util
     * @project AntTest
     * @blog http://blog.csdn.net/IBM_hoojo
     * @email hoojo_@126.com
     * @version 1.0
     */
    public class ExportIncrementFiles {
     
        /**
         * <b>function:</b> 導(dǎo)出增量文件
         * @author hoojo
         * @createDate 2013-11-2 下午10:15:43
         * @param configPath 增量文件路徑配置目錄
         * @param baseDir 基本路徑 目標(biāo)位置
         * @param destDir 增量文件保存位置
         * @throws Exception
         */
        private static void export(String configPath, String baseDir, String destDir) throws Exception {
            String srcFile = baseDir + configPath;
            String desFile = destDir + configPath;
            
            int lastIndex = desFile.lastIndexOf("/");
            String desPath = desFile.substring(0, lastIndex);
            
            File srcF = new File(srcFile);
            if(srcF.exists()){//如果不存在這樣的源文件,就不再拷貝,這個用來解決版本之間有刪除文件的情況。
                File desF = new File(desFile);
                File desP = new File(desPath);
                if(!desP.exists()) {
                    desP.mkdirs();
                }
                System.out.println(srcFile);
                FileInputStream fis = new FileInputStream(srcF);
                FileOutputStream fos = new FileOutputStream(desF);
                
                byte[] buf = new byte[1024];
                int len = 0;
                while((len = fis.read(buf)) != -1) {
                    fos.write(buf,0,len);
                }
                fos.flush();
                fos.close();
                fis.close();
            }
        }
        
        /**
         * <b>function:</b> 主函數(shù) 執(zhí)行導(dǎo)出增量包任務(wù)
         * @author hoojo
         * @createDate 2013-11-2 下午10:00:01
         * @param args 參數(shù)1 增量包導(dǎo)出文件路徑,參數(shù)2 要導(dǎo)出的文件的所在目標(biāo)位置,參數(shù)3 增量包導(dǎo)出保存的位置路徑
         */
        public static void main(String[] args) {
     
            if (args.length > 0) {
                if (args.length == 1 && "help".equals(args[0])) {
                    System.out.println("args[0] is Export Increment Files content path");
                    System.out.println("args[1] is Export Increment Files target path");
                    System.out.println("args[2] is Increment Files Export loaction");
                } else {
                    String configPath = args[0];
                    String baseDir = args[1];
                    String destDir = args[2];
                    
                    try {
                        BufferedReader br = new BufferedReader(new FileReader(configPath));
                        String s = null;
                        while((s = br.readLine()) != null) {
                            s = s.trim();//去掉路徑前面的空格
                            String str = destDir + s;
                            if(!destDir.equals(str)){//過濾空行
                                export(s, baseDir, destDir);
                            }
                        }
                        br.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    main函數(shù)參數(shù)看注釋,主要就是讀取patch.txt增量文件路徑,導(dǎo)出文件到指定目錄的。

     

    3、build 腳本

    <?xml version="1.0" encoding="UTF-8" ?>
    <!-- createDate 2013-10-28 -->
    <!-- author hoojo & http://blog.csdn.net/IBM_hoojo & http://hoojo.cnblogs.com -->
    <project default="checkout" basedir=".">
        <property file="build.properties"/>
        
        <!-- svn 比較項目最新路徑 -->
        <property name="svn.url" value="${svn._url}"/>
        <!-- svn 備份路徑-->
        <property name="bak.svn.url" value="${bak.svn._url}"/>
        
        <property name="svn.username" value="${svn.username}"/>
        <property name="svn.password" value="${svn.password}"/>
        
        <!-- 項目名稱 -->
        <property name="webapp" value="${webapp.name}"/>
        <!-- 目標(biāo)項目的Web 名稱(WEB-INF上一級的目錄名稱) -->
        <property name="webroot" value="${web.root}"/>
        
        <!-- svn改動文件列表信息 -->
        <property name="compare.path.file" value="${increment.file}"/>
        
        <!-- svn導(dǎo)出/切出文件存放目錄 -->
        <property name="dest.path" location="dest/${webapp}"/>
        <!-- svn導(dǎo)出/切出文件編譯后存放目錄 -->
        <property name="dist.path" location="dist/${webapp}"/>
        <!-- svn增量文件保存目錄 -->
        <property name="increment.dest.path" location="increment_dest/${webapp}"/>
        <!-- svn增量文件編譯后保存目錄 -->
        <property name="increment.dist.path" location="increment_dist/${webapp}"/>
        
        <!-- 利用jdt編譯class 解決泛型不能轉(zhuǎn)換的問題 需要將
            jdtCompilerAdapter.jar
            org.eclipse.jdt.compiler.tool_1.0.1.v_793_R33x.jar
            org.eclipse.jdt.core_3.3.3.v_793_R33x.jar
            org.eclipse.jdt.debug.ui_3.2.102.v20071002_r332.jar
            復(fù)制到ant_home/lib目錄下
        <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
        -->
        <path id="svnant.classpath">
            <fileset dir="${basedir}">
                <include name="**/*.jar"/>
            </fileset>
        </path>
        
        <path id="buildpath">
            <fileset dir="${dest.path}">
                <include name="**/lib/*.jar"/>
            </fileset>
            <fileset dir="C:/Program Files/Java/jdk1.6.0_13">
                <include name="**/*.jar"/>
            </fileset>
        </path>
        
        <typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="svnant.classpath"/>
        <svnSetting id="svn.settings" javahl="false" svnkit="true" username="${svn.username}" password="${svn.password}" failonerror="true"/>
        
        <target name="init" description="init clean dirs">
            <echo message="${svn.username}"/>
            <echo message="${svn.password}"/>
            <echo message="${webapp}"/>
            <echo message="${webroot}"/>
            <echo message="${compare.path.file}"/>
            
            <delete dir="${dest.path}" failonerror="false" deleteonexit="true" excludes="**/lib"/>
            <delete dir="${dist.path}" failonerror="false" deleteonexit="true" excludes="**/lib"/>
            <delete file="${compare.path.file}" failonerror="false"/>
            <delete dir="${increment.dest.path}" failonerror="false" deleteonexit="true"/>
            <delete dir="${increment.dist.path}" failonerror="false" deleteonexit="true"/>
        </target>
        
        <!-- that is to test i svnant is available //-->
        <target name="tool-available" depends="init">
            <echo message="run task test svnant is available"></echo>
            <available resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="svnant.classpath" property="available.svnant"/>
            <echo message="SVN-ANT is available = ${available.svnant}"></echo>
        </target>
        
        <!-- 比較差異 增量文件 -->
        <target name="diff" description="deff/compare project">
             <svn refid="svn.settings">
                <diffSummarize oldUrl="${bak.svn.url}" newUrl="${svn.url}" outFile="${compare.path.file}" recurse="true"/>
             </svn>
        </target>
            
        <!-- 下載 切成 導(dǎo)出 服務(wù)器上最新代碼 -->
        <target name="checkout" depends="tool-available" description="checkout/export project code ${svn.url} ">
            <echo message="checkout/export project code ${svn.url}"></echo>
            <svn refid="svn.settings">
                 <export srcUrl="${svn.url}" destPath="${dest.path}" revision="HEAD" force="true"/>
            </svn>
       </target>
        
        <!-- javac編譯 -->
        <target name="compile">
            <buildnumber/>
            <echo>compile ${dest.path} ......</echo>
            <delete dir="${dist.path}" failonerror="false" deleteonexit="true" excludes="**/lib"/>
            <mkdir dir="${dist.path}/classes"/>
            
            <javac nowarn="true" debug="${javac.debug}" debuglevel="${javac.debuglevel}" destdir="${dist.path}/classes" source="${javac.source}" target="${javac.target}" encoding="utf-8" fork="true" memoryMaximumSize="512m" includeantruntime="false">
                <src path="${dest.path}/src"/>
                <!--
                <compilerarg value="-Xlint:unchecked"/>
                <compilerarg value="-Xlint:deprecation"/>
                <compilerarg value="-Xlint"/>
                -->
                <classpath refid="buildpath"/>
                <classpath refid="svnant.classpath"/>
            </javac>
        </target>
        
        <!-- 利用JDT編譯 -->
        <target name="compile_jdt">
            <buildnumber/>
            <echo>compile ${dest_path} ......</echo>
            <delete dir="${dist_path}" failonerror="false" deleteonexit="true" excludes="**/lib"/>
            <mkdir dir="${dist_path}/classes"/>
            
            <javac compiler="org.eclipse.jdt.core.JDTCompilerAdapter" nowarn="true" debug="${javac.debug}" debuglevel="${javac.debuglevel}" destdir="${dist_path}/classes" source="${javac.source}" target="${javac.target}" encoding="utf-8" fork="true" memoryMaximumSize="512m" includeantruntime="false">
                <src path="${dest_path}/src"/>
                
                <classpath refid="buildpath"/>
                <classpath refid="svnant.classpath"/>
            </javac>
        </target>
        
        <!-- 利用JDT編譯SVN 最新項目 -->
        <target name="compile_svn">
            <!-- 回調(diào)任務(wù) -->
            <antcall target="compile_jdt">
                <param name="dest_path" value="${dest.path}"/>
                <param name="dist_path" value="${dist.path}"/>
            </antcall>
        </target>
        
        <!-- 將全部項目的class 建立jar包 -->
        <target name="jar" depends="compile_svn">
            <jar destfile="${basedir}/lib/${webapp}.jar" level="9" compress="true" encoding="utf-8" basedir="${dist.path}/classes">
                <manifest>
                    <attribute name="Implementation-Version" value="Version: 2.2"/>
                </manifest>
            </jar>
        </target>
        
        <!-- 導(dǎo)出增量文件 -->
        <target name="increment" depends="diff">
            <java classname="com.hoo.util.ExportIncrementFiles" classpath="${basedir}/lib/increment.export.jar" fork="true">
                <arg value="${compare.path.file}"/>
                <arg value="${dest.path}/"/>
                <arg value="${increment.dest.path}/"/>
            </java>
        </target>
     
        <!-- 利用JDT編譯增量文件 -->
        <target name="compile_increment">
            <antcall target="compile_jdt">
                <param name="dest_path" value="${increment.dest.path}"/>
                <param name="dist_path" value="${increment.dist.path}"/>
            </antcall>
        </target>
        
        <!-- 全部打包 -->    
        <target name="war">
            <echo>create war file.......</echo>
            
            <copy todir="${dist_path}" failonerror="false">
                <fileset dir="${dest_path}/${webroot}" includes="**"/>
            </copy>
            <move todir="${dist_path}/WEB-INF/classes" failonerror="false">
                <fileset dir="${dist_path}/classes" />
            </move>
            <copy todir="${dist_path}/WEB-INF/classes" failonerror="false">
                <fileset dir="${dest_path}/src/main/" includes="**/*.xml, **/*.properties, **/*.xsd"/>
                <fileset dir="${dest_path}/src/test/" includes="**/*.xml, **/*.properties, **/*.xsd"/>
                <fileset dir="${dest_path}/src/resource/" includes="**/*.xml, **/*.properties, **/*.xsd"/>
            </copy>
            
            <!--得到當(dāng)前日期--> 
            <tstamp> 
                <format property="DSTAMP" pattern="yyyyMMdd" locale="zh"/> 
                <format property="TSTAMP" pattern="HHmmss" locale="zh"/> 
            </tstamp> 
            
            <war destfile="${basedir}/${webapp}_${DSTAMP}_${TSTAMP}.war" basedir="${dist_path}" webxml="${dist_path}/WEB-INF/web.xml"/>        
        </target>
        
        <!-- 全部打包 -->    
        <target name="war_svn">
            <antcall target="war">
                <param name="dest_path" value="${dest.path}"/>
                <param name="dist_path" value="${dist.path}"/>
            </antcall>        
        </target>
        
        <!-- 全部打包 -->    
        <target name="war_increment">
            <copy todir="${increment.dist.path}/WEB-INF" file="${dest.path}/${webroot}/WEB-INF/web.xml"/>
            <antcall target="war">
                <param name="dest_path" value="${increment.dest.path}"/>
                <param name="dist_path" value="${increment.dist.path}"/>
            </antcall>        
        </target>
        
        <!-- svn 全量包 -->
        <target name="svn_war" depends="checkout, compile_svn, war_svn"/>
        <!-- 增量包 -->
        <target name="increment_war" depends="checkout, increment, jar, compile_increment, war_increment"/>
    </project>

     

    4、build的配置文件內(nèi)容

    #Mon, 04 Nov 2013 11:18:12 +0800
    svn._url=http://172.31.100.100/svn/iMVS_DataComm2
    bak.svn._url=http://172.31.100.100/svn/iMVS_DataComm
    svn.username=hoojo
    svn.password=mypass
    webapp.name=iMVS_DataComm
    web.root=WebRoot
    increment.file=patch.txt
     
    javac.debuglevel=source,lines,vars
    javac.target=1.6
    javac.source=1.6
    javac.debug=true

     

    運(yùn)行svn_war任務(wù)可以打全部的包,也就是svn最新地址的項目工程包。

    運(yùn)行increment_war任務(wù)可以打增量包,也會形成一個war文件。

    如果你需要發(fā)布到tomcat目錄,可以寫一個任務(wù)copy相關(guān)war包到tomcat的webapps的目錄下,這個很簡單~如果你需要調(diào)用tomcat的相關(guān)任務(wù)或命令,你需要在build腳本中加入

    <target name="_def_tomcat_tasks">
      <!-- tasks: deploy,undeploy,reload,stop,start,list,roles,resources -->
      <taskdef name="deploy"    classname="org.apache.catalina.ant.DeployTask" />
      <taskdef name="list"      classname="org.apache.catalina.ant.ListTask" />
      <taskdef name="reload"    classname="org.apache.catalina.ant.ReloadTask" />
      <taskdef name="resources" classname="org.apache.catalina.ant.ResourcesTask" />
      <taskdef name="roles"     classname="org.apache.catalina.ant.RolesTask" />
      <taskdef name="start"     classname="org.apache.catalina.ant.StartTask" />
      <taskdef name="stop"      classname="org.apache.catalina.ant.StopTask" />
      <taskdef name="undeploy"  classname="org.apache.catalina.ant.UndeployTask" />
    </target>

    關(guān)于這些命令使用方法有興趣的可以自己研究研究。

     

    四、總結(jié)

    整個流程稍微有點復(fù)雜,只要思路清晰這個build腳本還是很容易編寫的。前提是你要懂得Java發(fā)布、編譯、部署的流程,很多人用eclipse或MyEclipse來發(fā)布工程,好像很簡單。其實在工具背后也是使用這些腳本完成的,知道在用戶目錄下有一個 .m2的目錄么,這個就是eclipse工具的meven的緩存和配置的內(nèi)容。所以當(dāng)我們不使用這些ide的情況下,你怎么編譯、部署你的項目呢~!這篇文章只是一個拋磚引玉的效果,希望能給大家一個啟示。在這之前,我在網(wǎng)上搜集了些資料也沒有找到打增量包的比較好的方法,全都是手動方式。

    同時,在一些自動集成或持續(xù)集成的智能工具中,也大量的使用到了這方面的技術(shù)。如果你想更智能的完成這個項目的發(fā)布、部署的話,這里只是其中的第一步。有興趣的朋友可以研究下Continuous integration或Hudson等相關(guān)自動化集成技術(shù)應(yīng)用。



    作者:hoojo
    出處:
    blog:http://blog.csdn.net/IBM_hoojo
             http://hoojo.cnblogs.com
    本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。


    版權(quán)所有,轉(zhuǎn)載請注明出處 本文出自:
    分享道版權(quán)所有,歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處,謝謝

    評論:
    # re: 不會用ant打包、部署項目的工程師,不是一個好程序員(測試) 2013-11-05 12:31 | 魏五鎖業(yè)
    作為開發(fā)或測試,你一定要具備這種本領(lǐng)  回復(fù)  更多評論
      
    # re: 不會用ant打包、部署項目的工程師,不是一個好程序員(測試)[未登錄] 2014-11-19 13:30 | Jack
    用tortoise導(dǎo)出提交文件,在用myeclipse更新,對比src目錄考出.classes文件會方便的多  回復(fù)  更多評論
      
    主站蜘蛛池模板: 亚洲综合av永久无码精品一区二区| 久久精品无码专区免费| 成人免费视频试看120秒| 亚洲宅男精品一区在线观看| 国产91色综合久久免费分享| 亚洲欧洲精品一区二区三区| 7x7x7x免费在线观看| 4444亚洲国产成人精品| 免费无遮挡无码永久视频| 亚洲色图综合网站| 四虎成年永久免费网站| 亚洲av乱码一区二区三区| 成人性生活免费视频| 亚洲AV永久无码精品网站在线观看| 嫩草影院在线免费观看| 亚洲精品成a人在线观看☆| 国产成人免费片在线观看| 美女免费精品高清毛片在线视| 亚洲成片观看四虎永久| 久久久精品视频免费观看| 精品亚洲永久免费精品| 99热这里只有精品免费播放| 亚洲国色天香视频| 最近最新的免费中文字幕| 亚洲а∨精品天堂在线| 亚洲第一成人影院| 99精品视频免费| 久久精品国产亚洲AV嫖农村妇女| 69式国产真人免费视频| 亚洲第一街区偷拍街拍| 亚洲国产成人久久一区WWW| 99久久免费国产特黄| 中文字幕亚洲综合精品一区| 黄瓜视频高清在线看免费下载| 亚洲成在人线在线播放无码| 亚洲成a人片在线观看国产| 在线成人精品国产区免费| 亚洲短视频在线观看| 日本免费网站在线观看| 国产精品一区二区三区免费| 亚洲国产精久久久久久久|