zoukankan      html  css  js  c++  java
  • 初学maven五节

    【1】常见小问题集锦
    初学maven,遇到不少问题,记录下来,呵呵,依然是备忘兼共享。
     
    一. The pulgin 'org.apache.maven.plugins:maven-archetype-plugin' does not exist or valid version could be found 
     
        安装官方标准的安装方式(http://maven.apache.org/download.html#Installation)安装完毕,运行mvn --version没有问题。
        然后按照"maven in 5 minutes"(http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html) 的第一个例子,执行
    <!---->mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-app
        结果报错:
        The pulgin 'org.apache.maven.plugins:maven-archetype-plugin' does not exist or valid version could be found 
        ......
     
        google了一下发现解决方案,原来是网络配置的问题,如果使用代理上网必须修改maven的配置文件加入相应的代理信息。
        打开文件 maven/conf/settings.xml,找到<proxies>,将原来注释掉的<proxy>打开,修改相应的信息即可。
        注意:
        1.)<host>iproxy-sh.cn.ao.ericsson.se</host> 这里不要用"http://"开头,否则会无法连接
        2. ) 如果用户名、密码不需要,可以删除<username><password>,设置为空也行。
     
    二. artifactory私服安装问题
        对于单机来说,maven从远程仓库取jar包等资源是完全合理的。但是如果一个team甚至一个公司,每个人的maven都从远程仓库取,那么花在文件下载上的时间就太多了,而且完全没有必要。因此设置一个开发团队共享的Maven2的私服就必不可少了。
        Maven2的私服,当然首选artifactory。
        跑到artifactory的官网,down下来最新的1.30-beta1,安装非常简单,windows下一个bat文件直接启动。之后修改maven配置,加入
    <!----> <repositories>  
         <repository>  
             <id>central<!---->id>  
             <url>http://localhost:8081/artifactory/repo</url>  
             <snapshots>  
                 <enabled>false<!---->enabled>  
             <!---->snapshots>  
         <!---->repository>  
         <repository>  
             <id>snapshots<!---->id>  
             <url>http://localhost:8081/artifactory/repo</url>  
             <releases>  
                 <enabled>false<!---->enabled>  
             <!---->releases>  
         <!---->repository>  
     <!---->repositories>  
     <pluginRepositories>  
         <pluginRepository>  
             <id>central<!---->id>  
             <url>http://localhost:8081/artifactory/plugins-releases</url>  
             <snapshots>  
                 <enabled>false<!---->enabled>  
             <!---->snapshots>  
         <!---->pluginRepository>  
         <pluginRepository>  
             <id>snapshots<!---->id>  
             <url>http://localhost:8081/artifactory/plugins-snapshots</url>  
             <releases>  
                 <enabled>false<!---->enabled>  
             <!---->releases>  
         <!---->pluginRepository>  
     <!---->pluginRepositories>
        但是发现执行maven命令时,maven完全没有从私服上取文件,还是到默认的maven官网去取了。反复修改都不行,最后发现问题可能出现在artifactory上:登录artifactory的控制台后,点Virtual Repositories --》 repo 后直接报错,页面抛ArrayIndexOutOfBoundsException!看url是http://localhost:8081/artifactory/repo/,这个不就是上面配置的地址吗?都抛异常了,让maven怎么取文件,找到问题了,虽然莫名其妙,试着删除后重新安装还是这个错误。晕倒,不清楚哪里出的问题,更不知该怎么改。看看版本是beta1,而且下载数量只有几十,想想可能是新版本的bug。
        换成1.2.5final,一切都正常了。
        我想应该是artifactory 1.3.0-beta1的bug吧。
     
    三.maven的路径变量M2_REPO
         使用mvn eclipse:eclipse命令生成eclipse project后,在eclipse中impot进来,编译出错,原来是maven使用到一个名为“M2_REPO”的路径变量。
         google了一下,eclipse中设置变量M2_REPO的方式是:
            Window -> Preferences -> Java -> Build Path -> Classpath Variables,NewName 填写"M2_REPO",路径为你的本地的maven类库地址.
    设置后重新编译顺利通过,这样导入eclipse项目就完成了。
     
    【2】maven/artifactory/m2eclipse安装全过程
    前段时间研究过一下maven,中途因为工作忙搁置了一段时间,重新再看时发现安装过程基本忘光。只好找资料看然后再来一遍,将maven,artifactory和m2eclipse安装使用的全过程记录整理出来,备忘。另外我想这些资料应该比较适合maven的入门新手,照做一遍就可以完成三个东西的安装设置,然后就可以学习和使用了。
     
    一. 安装maven
        安装官方标准的安装方式(http://maven.apache.org/download.html#Installation)安装,步骤如下
        1. 下载解压缩apache-maven-2.0.9-bin.zip到安装目录
        2. 增加环境变量M2_HOME,指向maven的安装目录,注意不能以"\"结尾
        3. 增加(可选)maven环境变量MAVEN_OPTS,值为"-Xms256m -Xmx512m",后续可以增加其他
        4. 修改Path,增加%M2_HOME%/bin到Path路径中
        5. 确保JAVA_HOME环境变量存在并正确设置,确保%JAVA_HOME%/bin目录在Path路径中
        
        安装完毕后,在命令行执行"mvn --version"检测maven是否正确安装。
        
        补充:
        1. 如果是使用代理上网,需要在maven的配置文件加入相应的代理信息
            否则会报错:
            The pulgin 'org.apache.maven.plugins:maven-archetype-plugin' does not exist or valid version could be found
            ......
            解决方法:
            打开文件 maven/conf/settings.xml,找到<proxies>,将原来注释掉的<proxy>打开,修改相应的信息即可。
            注意:
            1.)<host>iproxy-sh.cn.ao.ericsson.se</host> 这里不要用"http://"开头,否则会无法连接
            2. ) 如果用户名、密码不需要,可以删除<username><password>,设置为空也行。
            
     
    二. 安装Artifactory
     
        按照官方文档,http://wiki.jfrog.org/confluence/display/RTF/Installing, 标准安装,简单说就是三步:
        1. 下载并解压缩最新版本的artifactory-1.3.0-beta-2.zip
        2. 双击bin目录下的artifactory.bat文件,启动artifactory。
            注意必须保证JAVA_HOME正确设置,并且jdk的版本是5.0或更高。
        3. 用浏览器打开http://localhost:8081/artifactory,使用admin/password登录
        
        配置Artifactory,在Artifactory安装目录下的etc目录下,比较常用的是修改jetty.xml中的端口设置,将默认的8081端口
        修改为其他。还有如果Artifactory是需要使用代码连接网络,需要修改artifactory.config.xml中的proxies。
        
    三. 安装m2eclipse插件
        
        参照官网文档http://m2eclipse.codehaus.org/。
        找了一下没有zip下载,只能用eclipse通过update site下载安装,无法使用我最喜欢的link方式,有些遗憾。
        安装地址如下:
            http://m2eclipse.sonatype.org/update/
        更新后会自动变成三个site,一个不可用,另外两个版本同步,有新旧两个版本可以选择,当然选最新的一个200807**的版本。
        
        安装好后,就可以使用m2eclipse插件为项目增加pom.xml文件了。有了m2eclipse的图形界面使得操作显得很简单,容易理解和掌握。
     
    update 20081128: 
        升级操作系统到vista,jdk到6.7,eclipse到3.4后,安装新版本的maven,一切正常,但是启动时会弹出窗口,说maven
    需要eclipse在jdk下运行,而不应该是jre(奇怪以前安装时怎么没有这种要求,难道是新版本引入的新功能?)。按照提示给出的建议进行以下操作:
     
    1.要求修改eclipse.ini文件
        加入两行代码,注意不要写在一行,否则无法生效。
        -vm
        C:\aoxj\soft\java\jdk\jdk67\bin\javaw
    2.设置installedJRE
        直接进入eclipse的设置,在installedJRE中加入新的jre指向jdk,然后将默认的jre删除。
        
    四. 技巧小结
        这几天的摸索中,发现一些maven和m2eclipse的使用小技巧,总结下来主要有以下几点:
        
        1. repositories设置不要放到项目的pom.xml文件中
            在使用Artifactory搭建私服后,肯定是需要将repositories设置为我们的私服地址的。下面的这段代码就可以完成我们
            的需要:
          <repositories>
            <repository>
                <id>artifactory</id>
                <name>local private artifactory</name>
                <url>http://127.0.0.1:8081/artifactory/repo/</url>
            </repository>
          </repositories>
            但是这段代码放到哪里比较好呢?按照maven的设置,可以放到%MAVEN_HOME%/conf/settings.xml, ~/.m2/settings.xml和
            项目的pom.xml文件中,上面三个设置可以覆盖,pom.xml中设置是最直接了当的。但是考虑到repositories信息是完全有
            可能变化的,尤其是使用私服,万一公司的私服换个地址难道所有项目的pom.xml文件都设置一遍? 还有pom.xml文件是用
            来保存当前项目的多种依赖信息的,repositories信息应该和当前具体项目没有直接联系。因此不应该放到pom.xml文件中。
            尤其在pom.xml文件需要保存到cvs,subversion等版本控制系统中,可变的repositories信息就更不合适保存了。
            因此需要将repositories信息设置在%MAVEN_HOME%/conf/settings.xml或~/.m2/settings.xml,这样就足够灵活了。
            
            实践中发现一个比较奇怪的地方,我使用的是maven2.0.9版本,修改%MAVEN_HOME%/conf/settings.xml设置居然无效,只能
            copy一份到~/.m2/settings.xml(这个文件默认是不会自动建立的),然后修改就可以正常生效了。没有查清楚原因,好在
            这两个地方对我没有实质区别,放~/.m2/也能接受,只是要记得备份一次避免重装系统时被删除。
            
        2. settings.xml设置repositories的最简单方式
            发现最简单的办法就是打开settings.xml文件最下面的activeProfiles设置:
            <activeprofiles>
                <activeprofile>artifactory</activeprofile>
            </activeprofiles>
            当然要先设置好对应的profile,对于简单场景,一个就足够了,这里我指向我搭建在本机的私服:
            
        <profile>
          <id>artifactory</id>
          <repositories>
            <repository>
                <id>artifactory</id>
                <name>local private artifactory</name>
                <url>http://127.0.0.1:8081/artifactory/repo/</url>
            </repository>
          </repositories>
          <pluginrepositories>
            <pluginrepository>
                <id>artifactory</id>
                <name>local private artifactory</name>
                <url>http://127.0.0.1:8081/artifactory/plugins-releases</url>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </pluginrepository>
        </pluginrepositories>
        </profile>
        
        顺便提一下settings.xml文件中localRepository的设置,这个设置用来知名localRepository的目录,默认不打开,使用默认值
        ~/.m2/repository,个人不喜欢,我就直接修改为固定位置:
        <localrepository>G:/soft/maven/localRepository</localrepository>
            
        3. dependency的classifier必须正确设置
            在下载testng时出现问题,始终无法从官网下载testng的jar包,但是可以下载到testng-5.8.pom文件。反复查找才发现是
            testng的jar包是区分jdk版本的,大家从这里可以看到
            http://repo1.maven.org/maven2/org/testng/testng/5.8/
            testng的jar包是有1.4和1.5的两种下载。增加classifier设置制定具体jdk版本之后就可以正常工作了。
            当然如果artifact没有jdk的差异就可以不需要设置这个参数。
            <dependency>
                <groupid>org.testng</groupid>
                <artifactid>testng</artifactid>
                <version>5.8</version>
                <classifier>jdk15</classifier>
            </dependency>
            
        4. groupId和artifactId的获取方式
            使用maven,很直接就会遇到这个问题,到底这个东西的groupId和artifactId是什么呢?总不能瞎猜吧?
            这里推荐这个artifact查询网站http://mvnrepository.com/,可以查找到25000+个artifact的信息,基本我们能用到的都
            有了。
            结合官网http://repo1.maven.org/maven2/ 页面,基本可以搞定所有问题。上面testng需要设置classifier的问题我就是看到
            http://repo1.maven.org/maven2/org/testng/testng/5.8/这个页面后才发现问题所在的。
     
        5. attifactory的http proxy设置
            上面attifactory安装时简单的介绍了一下 的http proxy设置,需要修改artifactory.config.xml中的<proxies>。但是这个是不够的,必须要再在<remoterepository>中明确用<proxyref>指明使用哪个代理,格式参考如下:
            <remoterepository>
                .........
                <url>http://people.apache.org/repo/m2-snapshot-repository</url>
                <proxyref>your-proxy</proxyref>
            </remoterepository>
    proxies中key要对应好
            <proxies>
                <proxy>
                <key>your-proxy</key>
                ......
            </proxies>
        
    五. 比较有价值的参考资料
        陆续google到的一些资料,比较好.
        maven官网的资料
            很全,很完整,非常值得看一遍,只是有点太多了,挺耗时间。而且是英文,暂时没有知道对应的中文版本。
        一些细碎的资料,主要是blog之类
        1) maven settings.xml 
            http://blog.csdn.net/totogogo/archive/2007/12/18/1946691.aspx
        2)  Maven dependency and repository
            http://blog.csdn.net/totogogo/archive/2007/12/20/1956381.aspx
        3)  maven profiles
            http://blog.csdn.net/totogogo/archive/2007/12/19/1953379.aspx
         
    【3】使用nexus替代artifactory作为maven私服
    之前看到过一些Nexus的介绍,由于刚开始接触maven时使用的私服是artifactory,因此没有太在意。今天想着既然Nexus能有胆量出来混,应该有点真本事才是,看了一下nexus的安装介绍,挺简单的,试试无妨。因此装上小试了一下,结果喜出望外,nexus的表现非常不错,尤其是在开启远程索引之后,简直太方便了。
     
        于是决定放弃artifactory改而使用nexus作为自己的maven私服。恩,惭愧,颇有点喜新厌旧的味道,artifactory才装上来没有几天,就惨遭抛弃......
     
        整理了一下,全过程记录如下:
     
    1. 首先下载Nexus
        从官网http://nexus.sonatype.org/download.html下载下载最新版本,因为是在windows上安装,因此下载的是zip版本,大小大概是16m。
        
    2. 安装
        简单解压缩下载的zip包到安装目录就可以了。
        可执行文件在%nexus安装目录%\nexus-webapp-1.0.0\binjsw\windows-x86-32下:
            InstallNexus.bat/UninstallNexus.bat是安装/卸载nexus为windows service,如果需要设置nexus为开机自动启动就可以安装为windows service然后设置启动方式为自动。
            Nexus.bat是直接在命令行中启动Nexus,如果不想安装Nexus为windows service,可以用这个文件来手工控制Nexus的启动退出。
            
            
    3. 配置nexus
     
        首先登录,默认地址http://localhost:8081/nexus/,默认用户名密码为admin/admin123.
        
        最重要的一件事情就是开启远程索引下载,索引这个功能实在是太好用了。
        
        nexus默认是关闭远程索引下载功能的,主要是担心会造成对服务器的巨大负担,需要我们手工开启。
        
        开启的方式:
            点击Administration菜单下面的Repositories,将这三个仓库Apache Snapshots,Codehaus Snapshots,Maven Central的Download Remote Indexes修改为true。然后在这三个仓库上分别右键,选择Re-index,这样Nexus就会去下载远程的索引文件。
            
    4. 配置maven
        要让maven使用nexus作为私服,需要做一些设置,使用和原来设置artifactory相似的方法。修改~/.m2/settings.xml.
        
        增加nexus的profile:
     
    <!---->    <profile>
          <id>nexus<!---->id>
          <repositories>
            <repository>
                <id>nexus<!---->id>
                <name>local private nexus<!---->name>
                <url>http://localhost:8081/nexus/content/groups/public<!---->url>
                <releases><enabled>true<!---->enabled><!---->releases>
                <snapshots><enabled>false<!---->enabled><!---->snapshots>
            <!---->repository>
            <repository>
                <id>nexus<!---->id>
                <name>local private nexus<!---->name>
                <url>http://localhost:8081/nexus/content/groups/public-snapshots<!---->url>
                <releases><enabled>false<!---->enabled><!---->releases>
                <snapshots><enabled>true<!---->enabled><!---->snapshots>
            <!---->repository>
          <!---->repositories>
          <pluginRepositories>
            <pluginRepository>
                <id>nexus<!---->id>
                <name>local private nexus<!---->name>
                <url>http://localhost:8081/nexus/content/groups/public<!---->url>
                <releases><enabled>true<!---->enabled><!---->releases>
                <snapshots><enabled>false<!---->enabled><!---->snapshots>
            <!---->pluginRepository>
            <pluginRepository>
                <id>nexus<!---->id>
                <name>local private nexus<!---->name>
                <url>http://localhost:8081/nexus/content/groups/public-snapshots<!---->url>
                <releases><enabled>false<!---->enabled><!---->releases>
                <snapshots><enabled>true<!---->enabled><!---->snapshots>
            <!---->pluginRepository>
           <!---->pluginRepositories>
        <!---->profile>
      
        修改activeProfiles为:
    <!---->      <activeProfiles>
            <activeProfile>nexus<!---->activeProfile>
          <!---->activeProfiles>
          
    5. 为nexus增加Artifact
        有些特殊的Artifact无法从maven官网仓库中下载,比如sun的一些包,只好自己自行下载后添加到私服中。
        在nexus中我选择将这些Artifact上传到默认安装就存在的仓库3rd Party中,右击仓库名,选择Upload Artifact。
        
    6. 在eclipse中使用索引功能
        原来试过,使用artifactory私服也可以使用Artifact的索引功能,但是由于不知道怎么设置远程仓库的index,我只会设置
        当前artifactory私服已有的Artifact的索引,对于还没有导入到artifactory私服的Artifact就没有办法索引了,很不方便,
        毕竟刚开始使用maven时,所有用到的Artifact都是本地和私服没有而需要到远程仓库取的。
        
        nexus中可以很方便的得到远程仓库的Artifact的索引,在上面“3. 配置nexus”就介绍过。下面介绍如何在eclispe里面
        设置和使用索引功能:
        1) 打开Maven Indexes 的eclispe view
            在eclispe中选择window -> show view -> other ... -> Maven -> Maven Indexes
        2) 添加nexus的index
            右键菜单中选"add index", 在弹出的"Add Respository index"窗口中填入:
                Repository URL: http://localhost:8081/nexus/content/groups/public
                Repository Id: nexus
                Index Update URL: 放空,暂时还不知道该怎么填
            加入后eclispe会自动load一次index信息,然后就可以在新加入的index下可以拉出极大数量的Artifact信息。
        3) 测试一下使用
            找个pom.xml文件,右键 -> Add Dependency, 然后填入一个关键词,比如我填入mina,马上填出和mina相关的一些
            选择,我找到apache mina,双击最新一个版本。会自动在pom.xml文件中增加以下内容:
     
    <!---->        <dependency>
                <groupId>org.apache.directory.mina<!---->groupId>
                <artifactId>mina-core<!---->artifactId>
                <version>0.9.5<!---->version>
            <!---->dependency>
     
            然后Maven自动下载jar包,再将jar包加入项目的build path,全程自动化处理,真是爽啊。
     
    7. 为nexus增加新的proxy  repository
            方法很简单,administration -> Repositories -> add -> proxy,填写后保存即可。但是要注意,nexus不会自动将新加入的repository添加到group中,而我们一般喜欢直接使用默认的"public repository" group, 比如前面我在maven的profile中就只设置了这一个URL: http://localhost:8081/nexus/content/groups/public。因此需要手工修改"public repository" group的设置,将刚才添加的proxy  repository加到组中。
            推荐的repository有:
                    1) jboss         http://repository.jboss.com/maven2/
                    2) sun            http://download.java.net/maven/2/
                    3)k-int           http://developer.k-int.com/maven2/
                            加入这个纯粹是因为它有sun的jmxri/jmxtools这些Artifact,强烈鄙视sun,自己的官方repository居然没有。
    8. 总结
        很明显,nexus无论是在界面,功能,操作上,都比artifactory强大的多。
        因此推荐大家使用nexus替代artifactory作为maven私服。
        
    updates:
    1.  2008.11.28  
    由于公司升级操作系统,告别老旧不堪的windows2000升级到vista,因此重新安装了nexus. 新版本的nexus似乎增加了不少小的功能比如对remote index的支持,具体没有深究,不过能不断更新实在是很令人欣慰。以后就打算用nexus了。
         
    【4】使用maven ant task实现非标准打包
    maven很强大,但是总有些事情干起来不是得心应手,没有使用ant时那种想怎么干就怎么干的流畅感。尤其当要打包一个特殊(相对maven的标准架构而且)时,常有不知所措的感觉。当然这个应该和自己对maven的了解不够有关,毕竟,“初学maven”嘛。
     
        但是maven在依赖管理方面实在是太强大了,太喜欢,退回原来的ant方式完全不可能,我想用过maven的人,一般是不会有回到原来在cvs,subversion中checkin/checkout n个jar包的时代,仅此一项理由就足够继续坚持使用maven了。
     
        然而ant的灵活又难于忘怀,尤其是从ant的build.xml一路走来的人,总是回不知不觉间想到ant的美好。鱼与熊掌,我都想要。最近想打包一个java应用,很简单但即不是标准的j2ee appication也不是web application, 用maven完全不知道该怎么打包,package出来的完全不是我想要的,在网上四处google maven资料的时候,总有用回ant拉倒的冲动。
     
        先交代一下背景吧,我要打包的程序,是这个样子:
     
        demo1
        |____lib
        |_____demo1.jar
        |_____*****.jar
        |_____*****.jar
        |____config
        |_____*****.properties
        |_____*****.xml
        |____log
        |_____*****.log
        |____run.bat
        |____run.sh
     
        这个应用的打包模式很简单,一个bat或者sh脚本用来执行,lib目录下存放所有的jar包,包括自己的源代码编译打包的jar和第三方包。config下是配置文件,这些文件需要在安装时或者运行前修改,比如监听的端口啊,数据库信息之类的。log目录存放日志文件。最后打包的产物是一个zip包(或者tar,tar.gz)。
     
        遇到的问题,就是maven标准的打包方式中根本不考虑类似的情况,什么jar,ear,war完全不适用。而且maven有些理念也诧异,比如maven标准的config目录是src/main/config,但是这个目录里面的配置文件默认会打包到jar包中,晕,都在jar里面了还让人怎么改啊?
        
        本着尽量只用maven不用ant的想法,我在maven的资料中看了好久,没有找到解决的方法。晕,难道大家都只打包标准的ear,jar,war,只有我这样无聊的人才会有这种打包的需求?
     
        几经寻觅和探索,最后发现,maven ant tasks似乎是一个不错的选择。带着mavenanttasks的官方文档和google上搜到的几篇文章,开始尝试,成功实现功能。现在将过程和方法share给大家。
     
        首先建立java项目anttaskdemo1,按照maven的推荐,文件结构如下:
     
        anttaskdemo1
        |____src/main/java
        |____src/main/config
        |____src/main/bin
        |____src/main/resources
        |____src/test/java
        |____src/test/resources
        |____target
        |____build.properties
        |____build.xml
        |____pom.xml
     
        其中src/main/java下放java代码;src/main/resources下放一个*.properties文件,这个资源文件是打包到jar中,内容打包之后不需要改变的。src/main/config下放一个标准的log4j.xml,这个是有在安装运行前临时修改的需要的。src/main/bin下放置可执行文件。
     
        1. 首先看pom.xml,标准内容,很简单,象征性的加入几个依赖
           
    <dependency>
                <groupId>commons-codec</groupId>
                <artifactId>commons-codec</artifactId>
                <version>1.3</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.13</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.testng</groupId>
                <artifactId>testng</artifactId>
                <version>5.8</version>
                <scope>test</scope>
                <classifier>jdk15</classifier>
            </dependency>
     
        其中commons-codec,log4j是需要打包到lib中的,运行时需要。testng(或者更一般的junit)是用来单元测试的,不需要打包到lib中。请注意它的设置"<scope>test</scope>"。
     
        2. 然后看看build.properties文件,这个内容不多:
        
    M2_REPO=G:/soft/maven/localRepository
     
    path.package=package
    path.target.name=anttaskdemo1
    path.package.lib=lib
    path.package.log=log
    path.package.config=config
    path.package.bin=
     
        
        M2_REPO稍后再详谈,后面的path.package之类的是最终打包时使用的几个目录名称,对应于最终打包的结构。
     
        3. build.xml,这个内容比较多。
     
        
    < xml version="1.0" encoding="UTF-8" >
    <project name="demo" default="all" xmlns:artifact="urn:maven-artifact-ant">
        <description>
        </description>
        <property file="build.properties" />
     
        <target name="init_maven">
            <!--
            remember to set M2_REPO before use this build.xml, for example in eclispe:
            "Window→Preferences→Ant→Runtime", add a new property named "M2_REPO" and set it value point to the path of your maven
            local repository; Or you can set it in build.properties.  You need do one (and only one) of them.
            -->
            <path id="maven-ant-tasks.classpath" path="${M2_REPO}/org/apache/maven/maven-ant-tasks/2.0.9/maven-ant-tasks-2.0.9.jar" />
            <typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath" />
     
            <artifact:pom id="maven.project" file="pom.xml" />
            <artifact:dependencies pathId="classpath.build" filesetid="maven.fileset.build">
                <pom refid="maven.project" />
            </artifact:dependencies>
            <artifact:dependencies pathId="classpath.runtime" filesetid="maven.fileset.runtime" useScope="runtime">
                <pom refid="maven.project" />
            </artifact:dependencies>
        </target>
     
        <target name="all" depends="init_path, compile, jar, package, zip" description="do all">
            <echo>begin to do all target to build the result package.</echo>
        </target>
     
        <target name="maven_info" depends="init_maven">
            <echo>Maven build directory is ${maven.project.build.directory}</echo>
            <echo>Maven build finalName is ${maven.project.build.finalName}</echo>
            <echo>Maven build sourceDirectory directory is ${maven.project.build.sourceDirectory}</echo>
            <echo>Maven build outputDirectory directory is ${maven.project.build.outputDirectory}</echo>
            <echo>Maven build scriptSourceDirectory directory is ${maven.project.build.testSourceDirectory}</echo>
            <echo>Maven build testOutputDirectory directory is ${maven.project.build.testOutputDirectory}</echo>
            <echo>Maven build scriptSourceDirectory directory is ${maven.project.build.scriptSourceDirectory}</echo>
            <echo>Maven build resourceDirectory directory is ${maven.project.build.resources}</echo>
     
            <property name="target.jar.name" value="${maven.project.build.directory}/${maven.project.build.finalName}.jar" />
            <echo>Maven build scriptSourceDirectory directory is ${target.jar.name}</echo>
        </target>
     
        <target name="clean" depends="init_maven">
            <echo>clean build directory : ${maven.project.build.directory}</echo>
            <delete dir="${maven.project.build.directory}" includes="**/*" />
        </target>
     
        <target name="init_path" depends="maven_info, clean">
            <echo>make dir for java compile: ${maven.project.build.outputDirectory}</echo>
            <mkdir dir="${maven.project.build.outputDirectory}" />
        </target>
     
        <target name="compile" description="description" depends="init_maven">
            <javac srcdir="${maven.project.build.sourceDirectory}" destdir="${maven.project.build.outputDirectory}" classpathref="classpath.build" />
        </target>
        <target name="copyResource" depends="init_maven">
            <copy todir="${maven.project.build.outputDirectory}">
                <fileset dir="src/main/resources">
                </fileset>
            </copy>
        </target>
     
        <target name="jar" depends="compile, copyResource">
            <delete file="${maven.project.build.directory}/${maven.project.build.finalName}.jar"  failonerror="false" />
            <jar destfile="${maven.project.build.directory}/${maven.project.build.finalName}.jar" basedir="${maven.project.build.outputDirectory}">
            </jar>
        </target>
     
        <target name="package" depends="package_prepare, copyLib, copyConfig, copyBin">
        </target>
     
        <target name="package_prepare" depends="init_maven">
            <echo>clean package directory : ${maven.project.build.directory}/${path.package}</echo>
            <delete dir="${maven.project.build.directory}/${path.package}" />
            <mkdir dir="${maven.project.build.directory}/${path.package}" />
            <mkdir dir="${maven.project.build.directory}/${path.package}/${path.target.name}" />
            <mkdir dir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.lib}" />
            <mkdir dir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.config}" />
            <mkdir dir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.log}" />
        </target>
     
        <target name="copyLib" depends="init_maven">
            <copy todir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.lib}">
                <fileset refid="maven.fileset.runtime" />
                <mapper type="flatten" />
            </copy>
            <copy todir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.lib}"
                file="${maven.project.build.directory}/${maven.project.build.finalName}.jar">
     
            </copy>
        </target>
        <target name="copyConfig" depends="init_maven">
            <copy todir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.config}">
                <fileset dir="src/main/config">
                </fileset>
            </copy>
        </target>
        <target name="copyBin" depends="init_maven">
            <copy todir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.bin}">
                <fileset dir="src/main/bin">
                </fileset>
            </copy>
        </target>
        <target name="zip" depends="init_maven">
            <zip destfile="${maven.project.build.directory}/${path.package}/${path.target.name}.zip">
                <fileset dir="${maven.project.build.directory}/${path.package}/${path.target.name}"></fileset>
            </zip>
        </target>
    </project>
     
        一步一步来讲吧:
     
        3.1 最重要的一步,init_maven
     
        <target name="init_maven">
            <!--
            remember to set M2_REPO before use this build.xml, for example in eclispe:
            "Window→Preferences→Ant→Runtime", add a new property named "M2_REPO" and set it value point to the path of your maven
            local repository; Or you can set it in build.properties.  You need do one (and only one) of them.
            -->
            <path id="maven-ant-tasks.classpath" path="${M2_REPO}/org/apache/maven/maven-ant-tasks/2.0.9/maven-ant-tasks-2.0.9.jar" />
            <typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath" />
     
            <artifact:pom id="maven.project" file="pom.xml" />
            <artifact:dependencies pathId="classpath.build" filesetid="maven.fileset.build">
                <pom refid="maven.project" />
            </artifact:dependencies>
            <artifact:dependencies pathId="classpath.runtime" filesetid="maven.fileset.runtime" useScope="runtime">
                <pom refid="maven.project" />
            </artifact:dependencies>
        </target>
     
     
        在ant中使用maven-ant-tasks,就需要装载maven-ant-tasks的jar包,方法有两种,一种是直接将maven-ant-tasks-2.0.9.jar放到ant的lib下,自然就可以直接使用。但是个人感觉不怎么喜欢这种方式,我采用的是第二种,在ant的build.xml文件中装载:
     
            <path id="maven-ant-tasks.classpath" path="${M2_REPO}/org/apache/maven/maven-ant-tasks/2.0.9/maven-ant-tasks-2.0.9.jar" />
            <typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath" />
     
     
        这样就可以在后面使用maven-ant-tasks的task,比如artifact:pom,artifact:dependencies。<path />用于指定maven-ant-tasks-2.0.9.jar的路径,这里就有点麻烦了:maven-ant-tasks-2.0.9.jar这个东西放哪里好呢?直接放到项目中,然后存放到cvs/svn?显然不是一个好办法。考虑到maven本来就是干保存jar这行的,交给maven好了。maven-ant-tasks-2.0.9.jar本来就是一个依赖,可以在http://mvnrepository.com/找到:
        http://mvnrepository.com/artifact/org.apache.maven/maven-ant-tasks
        pom内容如下:
        <dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-ant-tasks</artifactId>
        <version>2.0.9</version>
    </dependency> 
     
        将这个内容随便找个空项目,加入后update一下dependency,在本地的maven repository中就会有它的jar文件。然后就可以直接使用它。
        ${M2_REPO},这个是eclipse中通用的指向maven local repository的变量,大家使用maven命令建立eclipse项目时会遇到它。我们在这里可以直接使用这个变量来访问maven local repository。如果没有建立这个变量,请自行建立,上面注释中有详细说明。如果在eclispe之外比如命令行直接运行ant打包,则可以通过设置build.properties文件中的“M2_REPO=G:/soft/maven/localRepository”来指定。(这里用到ant的一个特性,属性一旦被赋值就不能修改,因此第一次赋值有效,在eclispe中运行,M2_REPO会使用eclispe中设置的值,如果eclispe没有设置或者命令行直接运行,M2_REPO属性会在build.properties文件装载时设置。)
     
        装载ok后,接着是调用artifact:pom和artifact:dependencies 任务来指定pom.xml文件,再得到dependencies信息,后面的编译打包会使用到。注意useScope="runtime",这个是为了最后打包时使用,只复制runtie时需要的jar包。
     
        <target name="maven_info" />是用来打印maven相关的一些信息的,比如maven下的几个build目录。artifact:pom任务装载了整个pom,因此在后面可以访问到pom的信息,比如${maven.project.build.sourceDirectory}是java源代码目录,${maven.project.build.finalName}是最终的名称。
     
        pom的内容可以参考这两个官方资料:
     
        1) maven model
            http://maven.apache.org/ref/2.0.9/maven-model/maven.html
     
        2) Introduction to the POM
            http://maven.apache.org/guides/introduction/introduction-to-the-pom.html
     
        标准目录布局可以参考这个官方资料:
     
            http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
     
        3.2 compile
     
            这里是maven ant task的精髓所在,
        <target name="compile" description="description" depends="init_maven">
            <javac srcdir="${maven.project.build.sourceDirectory}" destdir="${maven.project.build.outputDirectory}" classpathref="classpath.build" />
        </target>
     
            结合之前maven初始化时的情况:
            <artifact:pom id="maven.project" file="pom.xml" />
            <artifact:dependencies pathId="classpath.build" filesetid="maven.fileset.build">
                <pom refid="maven.project" />
            </artifact:dependencies>
     
     
        可以看到,我们的项目完全遵循maven的标准做法,然后ant通过访问pom来得到相关的路径信息和classpath信息,完美结合。
        target copyResource 完成了将resource copy到outputDirectory的任务,这里的resource都是classpath resource。
        注: 这个有个问题,就是我没有找到通过pom得到resouce目录的方法,${maven.project.build.resources 只能得到pom文件中<resources/>, 对于里面包含的<resource>不知道该用什么方式来访问,如默认的:
        <resources>
          <resource>
            <directory>src/main/resources</directory>
          </resource>
        </resources>
     
        我试过用${maven.project.build.resources[0];${maven.project.build.resources(0), ${maven.project.build.resources.0,${maven.project.build.resources.resource
    等都无效。找了很久都没有找到资料,只好作罢。直接写死src/main/resources吧。
     
        3.3 jar
            和compile类似,标准的ant jar,然后通过访问pom来得到相关的路径信息和打包文件名。注意这里的文件名和路径和maven的做法一致,也就是说和执行maven的compile命令结果是一样的。
        <target name="jar" depends="compile, copyResource">
            <delete file="${maven.project.build.directory}/${maven.project.build.finalName}.jar"  failonerror="false" />
            <jar destfile="${maven.project.build.directory}/${maven.project.build.finalName}.jar" basedir="${maven.project.build.outputDirectory}">
            </jar>
        </target>
     
     
        3.4 package, zip
        package_prepare, copyLib, copyConfig, copyBin 这几个target都简单,体力活而已。zip也是。
     
        
        4. 总结
        
            上面的内容虽多,但是总结起来就只有两点:
        1. maven ant task可以将maven的功能和ant的灵活性统一起来,对于非标准的打包情况非常适用
        2. maven ant task的使用并不难,不过需要掌握不少maven的基本知识,比如pom,标准目录布局等。
     
            另外,似乎,ant + Ivy会是更好的选择?
  • 相关阅读:
    服务器管理注意事项
    帮朋友发个招聘信息
    tcp/ip协议简介
    程序员的本质(转)
    不同部门员工吃饭时聊些什么
    IE用户比Opera和Chrome用户的IQ低
    有一天,程序猿们突然发现他们要涨的工资掉到井里啦!大家都很害怕,连忙一个吊着一个,从树上伸到井里去捞工资。正好他们摸到工资的时候,一个老程序员忽然兴奋的大叫:别蠢了,要涨的工资还好好的挂在天上呢!
    asp.net使用缓存造成iis重启的问题
    Win批量修改文件名&扩展名
    引用变量位于Java虚拟机的运行时数据区的情况分析
  • 原文地址:https://www.cnblogs.com/huapox/p/3251621.html
Copyright © 2011-2022 走看看