Maven 专题之一 (转自http://blog.youkuaiyun.com/maoxiang)

本文对比了Maven和Ant,指出Maven在编译脚本基础、依赖包定义、中央仓库编译、重用脚本等方面更具优势,虽缺少成熟GUI界面但节省时间。还介绍了build.properties和project.properties的用途,多项目开发、自定义模板等使用技巧,以及常见问题的解决办法。

1  mavenant的比较

 第一:每次和别人说maven的时候,很多会认为是全新的东西而不肯放弃ant。其实,ant脚本是可以直接运行在maven中的。

如果要说mavenant有什么差别,我觉得最大的差别就是在于maven的编译以及所有的脚本都有一个基础,就是POMproject object model)。这个模型定义了项目的方方面面,然后各式各样的脚本在这个模型上工作,而ant完全是自己定义,显然maven更胜一筹。

第二:Maven对所依赖的包有明确的定义,如使用那个包,版本是多少,一目了然。而ant则通常是简单的inclde 所有的jar。导致的最终结果就是,你根本无法确定JBoss中的lib下的commonlogging 是哪个版本的,唯一的方法就是打开 METAINF 目录下MANIFEST.MF。估计JBoss迟早会转向Maven的。

第三:Maven是基于中央仓库的编译,即把编译所需要的资源放在一个中央仓库里,如jartldpom,等。当编译的时候,maven会自动在仓库中找到相应的包,如果本地仓库没有,则从设定好的远程仓库中下载到本地。这一切都是自动的,而ant需要自己定义了。这个好处导致的结果就是,用maven编译的项目在发布的时候只需要发布源码,小得很,而反之,ant的发布则要把所有的包一起发布,显然maven又胜了一筹。

第四:maven有大量的重用脚本可以利用,如生成网站,生成javadocsourcecode reference,等。而ant都需要自己去写。试试 maven site 的效果。

第五:maven目前不足的地方就是没有象ant那样成熟的GUI界面,不过mavengui正在努力中。目前使用maven最好的方法还是命令行,又快又方便。

 

最后,总结一下,转向maven会为你节省更多的时间。

 

2. build.properties project.properties

  build.properties 用来方编译信息比较好,project.properties用来放项目信息比较好。

Build.properties的实例,把他放在用户目录下(C:/Documents and Settings/user),就可以使用所有项目都共享这个信息。

maven.repo.local=f:/java/repository

maven.repo.remote=http://mirrors.sunsite.dk/maven/

 

#maven.proxy.host=127.0.0.1

#maven.proxy.port=80

 

maven.compile.target = 1.4

maven.compile.source = 1.4

 

3 如何进行多个项目的开发。

 

在用Maven进行一个项目下有多个子项目开发的时候,常用的就是MulitProject 脚本 <maven:reactor >

 

举例来看,下图就是一个项目中的子项目,该子项目又有两个子项目,只要在project中定义了继承关系,1.0能够将maven.xml中的脚本及project.properties build.properties中的属性 传播到子项目中去,这个特性好像在RC版本中没有完全实现。

 

 知道了Maven 的这些特性,就可以将大量的公共脚本写在mavenxml中,子项目就可以很方便的调用了。

 

         <!--==================================================================-->

<!-- Hibernate Doclet-->

<!--==================================================================-->

<goal description="xdoclet for hibernate " name="project:hibernate-xdoclet">

<taskdef name="hibernatedoclet"

classname="xdoclet.modules.hibernate.HibernateDocletTask"

classpathref="maven.dependency.classpath"/>

<echo>+---------------------------------------------------+</echo>

<echo>| Hibernate Doclet......                                       |</echo>

<echo>+---------------------------------------------------+</echo>

<mkdir dir="${project.xdoclet.hibernate.destDir}"/>

<hibernatedoclet destdir="${project.xdoclet.hibernate.destDir}"

mergedir="${project.xdoclet.hibernate.mergeDir}"

excludedtags="${project.xdoclet.hibernate.excludedtags}"

addedtags="${project.xdoclet.hibernate.addedtags}"

force="${project.xdoclet.hibernate.force}"

verbose="${project.xdoclet.hibernate.verbose}">

<fileset dir="${project.xdoclet.hibernate.srcDir}">

<include name="**/*.java"/>

</fileset>

<hibernate version="2.0"/>

<!--

<jbossservice

transactionStrategy="${project.xdoclet.hibernate.jbossservice.transactionStrategy}"

userTransactionName ="${project.xdoclet.hibernate.jbossservice.userTransactionName}"

serviceName="${project.xdoclet.hibernate.jbossservice.serviceName}"

jndiName="${project.xdoclet.hibernate.jbossservice.jndiName}"

dataSource="${project.xdoclet.hibernate.jbossservice.dataSource}"

dialect="${project.xdoclet.hibernate.jbossservice.dialect}"

showSql="${project.xdoclet.hibernate.jbossservice.showSql}"

templateFile="${project.xdoclet.hibernate.jbossservice.templateFile}"

/>

-->

<hibernatecfg

transactionManagerLookup="${project.xdoclet.hibernate.cfg.transactionManagerLookup}"

transactionStrategy="${project.xdoclet.hibernate.cfg.transactionStrategy}"

userTransactionName

="${project.xdoclet.hibernate.cfg.userTransactionName}"

jndiName="${project.xdoclet.hibernate.cfg.jndiName}"

dataSource="${project.xdoclet.hibernate.cfg.dataSource}"

dialect="${project.xdoclet.hibernate.cfg.dialect}"

showSql="${project.xdoclet.hibernate.cfg.showSql}" />

</hibernatedoclet>

</goal>

 

在任何一个子项目中,就可以直接调用project:hibernate-xdoclet脚本了。就可以

 

<maven:reactor 的不足在于,如果你这样定义

<maven:reactor basedir="${basedir}" postProcessing="true"

includes="portal/project.xml,common/project.xml" goals="project:deploy"

banner="Deploying Service:" ignoreFailures="false" />

 

本来原意是想让Portal早于common进行编译,不过reactor实际将先编译common,再编译portal。因为他是以名称来决定编译次序,显然是不好的,因为多个子项目之间往往是有先后关系。解决的方法就是,定义多个reactor 了。

 

4 定义自己的maven.xml 模板。

 maven的脚本是基于AOP的,也就是你可以在任何一个goal之前和之后插入自己的代码,所以maven的脚本没有固定的写法。

这里有我写过的一个maven模板。

<?xml version="1.0" encoding="gb2312"?>

<project default="project:deploy" xmlns:maven="jelly:maven"

xmlns:j="jelly:core" xmlns:util="jelly:util">

<!-- 一般项目分为四个里程碑:初始化、精化、构建、部署 -->

<preGoal name="project:deploy">

<attainGoal name="project:inception"/>

<attainGoal name="project:elaboration"/>

<attainGoal name="project:construction"/>

<attainGoal name="project:transition"/>

</preGoal>

<goal name="project:deploy">

</goal>

<!--完成一些初始化工作 -->

<goal name="project:inception">

<attainGoal name="clean"/>

</goal>

<!-- 主要是xdoclet 产生各种文件-->

<goal name="project:elaboration">

    <attainGoal name="project:ejb-xdoclet"/>

</goal>

<!-- 编译项目-->

<goal name="project:construction">

<!-- 调用war 插件 -->

<attainGoal name="war:war"/>

</goal>

<!--

对编译好的项目进行组合准备部署

-->

<goal name="project:transition">

</goal>

</project>

 

5 很多公共脚本都不正常

这是很正常的事情,事实上很多脚本 xdocletmiddlegen等都存在一定的问题,如果出现这种情况,最直接的办法就是把它们的脚本自己封装一遍,做成适合自己的脚本。

比如,xdoclet 1.2之前的脚本就不太好用,我就到mavencache目录(C:/Documents and Settings/user/.maven/cache),找到想修改的插件目录,里面都会有plugin.jelly,它是一个xml文件,里面就是脚本了,然后copy到自己的maven.xml中,就可以直接调用了。

以下,是我写的自己常用的web xdoclet脚本

 

         <!--==================================================================-->

<!-- WEB Doclet-->

<!--==================================================================-->

<goal description="xdoclet for web " name="project:web-xdoclet" >

<taskdef name="webdoclet" classname="xdoclet.modules.web.WebDocletTask"

classpathref="maven.dependency.classpath"/>

<echo>+---------------------------------------------------+</echo>

<echo>| Running WebDoclet...... |</echo>

<echo>+---------------------------------------------------+</echo>

<mkdir dir="${project.xdoclet.web.destDir}"/>

<webdoclet destdir="${project.xdoclet.web.destDir}"

mergedir="${project.xdoclet.web.mergeDir}"

excludedtags="${project.xdoclet.web.excludedtags}"

addedtags="${project.xdoclet.web.addedtags}"

force="${project.xdoclet.web.force}"

verbose="${project.xdoclet.web.verbose}">

<fileset dir="${project.xdoclet.web.srcDir}">

<include name="**/*.java"/>

</fileset>

<deploymentdescriptor servletspec="${project.xdoclet.web.version}"

destdir="${project.xdoclet.web.webxml.dir}"

xmlencoding="${project.xdoclet.web.xmlencoding}"

templateFile="${project.xdoclet.web.templateFile}" />

<strutsconfigxml

destdir="${project.xdoclet.web.strutsconfigxml.dir}"

xmlencoding="${project.xdoclet.web.strutsconfigxml.xmlencoding}"

version="${project.xdoclet.web.strutsconfigxml.version}"

templateFile="${project.xdoclet.web.strutsconfigxml.templateFile}"

/>

<jsptaglib jspversion="${project.xdoclet.web.jsptaglib.version}"

destdir="${project.xdoclet.web.jsptaglib.dir}"

shortname="${project.xdoclet.web.jsptaglib.shortname}"

validateXml="${project.xdoclet.web.jsptaglib.validatexml}"

xmlencoding="${project.xdoclet.web.jsptaglib.xmlencoding}"

filename="${project.xdoclet.web.jsptaglib.filename}"

templateFile="${project.xdoclet.web.jsptaglib.templateFile}" />

<!--

<jbosswebxml destdir="${project.xdoclet.web.jbosswebxml.dir}"

mergeDir="${project.xdoclet.web.jbosswebxml.dir}"/>

-->

</webdoclet>

</goal>

 

这个脚本可以生成web.xml struts-config.xml  tld jboss-web.xml ,自己可以根据需要很方便的修改了。其实不难看出,这些都是ant脚本。所以,如果没有合适的插件,最好的方法就是自己动手写一个。

 

6 无法运行maven,报错为 缺少根组件。

 这个错误是因为你采用的编辑器(比如:ultraedit)在<?xml 前添加了多余的字符,导致xml解析器无法处理xml文件,这个错误常常遇到。解决的方法就是把内容copy下来,重新paste到新的文件,覆盖老文件。或者用别的编辑器把多余字符去掉。

 

ERROR] Plugin org.apache.maven.plugins:maven-surefire-plugin:2.5 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-surefire-plugin:jar:2.5: Could not transfer artifact org.apache.maven.plugins:maven-surefire-plugin:pom:2.5 from/to tplink-mvn (http://rdsource.tp-link.net/maven-public/): Transfer failed for http://rdsource.tp-link.net/maven-public/org/apache/maven/plugins/maven-surefire-plugin/2.5/maven-surefire-plugin-2.5.pom: Unknown host rdsource.tp-link.net: Name or service not known -> [Help 1] [ERROR] Plugin org.apache.maven.plugins:maven-surefire-plugin:2.5 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-surefire-plugin:jar:2.5: Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.5 from http://rdsource.tp-link.net/maven-public/ was cached in the local repository, resolution will not be reattempted until the update interval of tplink-mvn has elapsed or updates are forced. Original error: Could not transfer artifact org.apache.maven.plugins:maven-surefire-plugin:pom:2.5 from/to tplink-mvn (http://rdsource.tp-link.net/maven-public/): Transfer failed for http://rdsource.tp-link.net/maven-public/org/apache/maven/plugins/maven-surefire-plugin/2.5/maven-surefire-plugin-2.5.pom -> [Help 1] [ERROR] Plugin org.apache.maven.plugins:maven-surefire-plugin:2.5 or one of its dependencies could not be resolved: Failed to read artifact descriptor for org.apache.maven.plugins:maven-surefire-plugin:jar:2.5: Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.5 from http://rdsource.tp-link.net/maven-public/ was cached in the local repository, resolution will not be reattempted until the update interval of tplink-mvn has elapsed or updates are forced. Original error: Could not transfer artifact org.apache.maven.plugins:maven-surefire-plugin:pom:2.5 from/to tplink-mvn (http://rdsource.tp-link.net/maven-public/): Transfer failed for http://rdsource.tp-link.net/maven-public/org/apache/maven/plugins/maven-surefire-plugin/2.5/maven-surefire-plugin-2.5.pom
最新发布
12-12
<think>我们遇到了Maven构建错误,主要问题是无法从公司内部的Maven仓库(tplink-mvn)下载maven-surefire-plugin:2.5插件。错误信息显示“Unknown host rdsource.tp-link.net”,这意味着该域名无法解析。 ### 解决步骤: 1. **检查网络连接和域名解析**: ```bash ping rdsource.tp-link.net ``` - 如果无法解析,可能是DNS问题或内部仓库地址变更 2. **检查Maven的settings.xml配置**: - 确认`tplink-mvn`仓库的URL是否正确 - 检查是否有权限访问该仓库 3. **清除Maven本地缓存**(强制重新下载): ```bash mvn dependency:purge-local-repository -DreResolve=false ``` 或手动删除本地仓库中相关文件: ```bash rm -rf ~/.m2/repository/org/apache/maven/plugins/maven-surefire-plugin/2.5 ``` 4. **强制更新Maven依赖**: ```bash mvn clean install -U ``` 5. **临时解决方案(如果内部仓库不可用)**: - 在pom.xml中添加Maven中央仓库作为备用: ```xml <repositories> <repository> <id>central</id> <url>https://repo.maven.apache.org/maven2</url> </repository> </repositories> ``` ### 完整错误分析: - 根本原因:无法访问 `http://rdsource.tp-link.net/maven-public/` - 可能情况: - 内部仓库地址变更 - 网络权限问题 - 本地DNS配置错误 §§相关问题§§ 1. 如何验证Maven仓库URL是否可以从当前网络环境访问? 2.Maven中如何配置多个仓库以提供备用下载源? 3. 除了清除本地缓存,还有哪些方法可以解决Maven依赖下载失败的问题? 4. 如何检查Maven构建过程中具体使用了哪些仓库设置? 5. 当遇到插件下载失败时,如何临时跳过测试执行(skip tests)继续构建? </think> 这个错误表明 Maven 无法下载所需的 `maven-surefire-plugin` 插件,主要原因是无法解析仓库域名 `rdsource.tp-link.net`。以下是解决方案: ### 解决步骤: 1. **检查网络连接**: ```bash ping rdsource.tp-link.net ``` 如果无法解析,说明是 DNS 问题或网络限制 2. **清除 Maven 本地缓存**: ```bash mvn dependency:purge-local-repository ``` 或手动删除相关目录: ```bash rm -rf ~/.m2/repository/org/apache/maven/plugins/maven-surefire-plugin ``` 3. **强制更新依赖**(使用 `-U` 参数): ```bash mvn clean install -U ``` 4. **检查 settings.xml 配置**: 确保没有错误的仓库配置: ```bash # 查看全局配置 cat ~/.m2/settings.xml # 查看项目配置 cat /path/to/project/pom.xml ``` 5. **临时解决方案**(使用公共仓库): 在 pom.xml 中添加 Maven 中央仓库: ```xml <repositories> <repository> <id>central</id> <url>https://repo.maven.apache.org/maven2</url> </repository> </repositories> ``` ### 错误原因分析: | 问题类型 | 具体原因 | 解决方案 | |----------|----------|----------| | **网络问题** | 无法解析 `rdsource.tp-link.net` | 检查网络/DNS,或改用公共仓库 | | **仓库配置错误** | settings.xml 中配置了无效仓库 | 移除或修正错误仓库配置 | | **本地缓存损坏** | 之前下载失败的缓存阻止重试 | 清除本地仓库缓存 | | **插件版本过旧** | 2.5 版本可能不再维护 | 尝试升级到更新版本 | > **重要提示**:如果 `rdsource.tp-link.net` 是您公司的内部仓库,请联系网络管理员确认仓库状态和访问权限。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值