锁定老帖子 主题:maven常见问题问答
精华帖 (17) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
作者 | 正文 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-03-23
最后修改:2011-03-23
前言Maven,发音是[`meivin],"专家"的意思。它是一个很好的项目管理工具,很早就进入了我的必备工具行列,但是这次为了把ABPM项目 完全迁移并应用maven,所以对maven进行了一些深入的学习。写这个学习笔记的目的,一个是为了自己备忘,二则希望能够为其他人学习使用maven 缩短一些时间。 maven概要首先我把maven的概念快速的梳理一下,让我们快速地建立起一个比较精确的maven应用场景。 maven不是什么读书时候要先限定范围,避免一些有害的遐想。要说maven不是什么,我们可以从如下几个要点来展开
maven是什么maven将自己定位为一个项目管理工具。它负责管理项目开发过程中的几乎所有的东西:
maven的生命周期maven把项目的构建划分为不同的生命周期(lifecycle),在我看来,划分的已经是非常仔细了,大家可以参考这里 。粗略一点的话,它这个过程(phase)包括:编译、测试、打包、集成测试、验证、部署。maven中所有的执行动作(goal)都需要指明自己在这个过程中的执行位置,然后maven执行的时候,就依照过程的发展依次调用这些goal进行各种处理。 这个也是maven的一个基本调度机制。一般来说,位置稍后的过程都会依赖于之前的过程。当然,maven同样提供了配置文件,可以依照用户要求,跳过某些阶段。 maven的"约定优于配置"所谓的"约定优于配置",在maven中并不是完全不可以修改的,他们只是一些配置的默认值而已。但是使用者除非必要,并不需要去修改那些约定内容。maven默认的文件存放结构如下:
每一个阶段的任务都知道怎么正确完成自己的工作,比如compile任务就知道从src/main/java下编译所有的java文件,并把它的输出class文件存放到target/classes中。 对maven来说,采用"约定优于配置"的策略可以减少修改配置的工作量,也可以降低学习成本,更重要的是,给项目引入了统一的规范。 maven的版本规范maven使用如下几个要素来唯一定位某一个输出物: groupId:artifactId:packaging:version 。比如 org.springframework:spring:2.5 。每个部分的解释如下:
maven有自己的版本规范,一般是如下定义 <major version>.<minor version>.<incremental version>-<qualifier> , 比如1.2.3-beta-01。要说明的是,maven自己判断版本的算法是major,minor,incremental部分用数字比 较,qualifier部分用字符串比较,所以要小心 alpha-2和alpha-15的比较关系,最好用 alpha-02的格式。 maven在版本管理时候可以使用几个特殊的字符串 SNAPSHOT ,LATEST ,RELEASE 。比如"1.0-SNAPSHOT"。各个部分的含义和处理逻辑如下说明:
maven的组成部分maven把整个maven管理的项目分为几个部分,一个部分是源代码,包括源代码本身、相关的各种资源,一个部分则是单元测试用例,另外一部分则是各种maven的插件。对于这几个部分,maven可以独立管理他们,包括各种外部依赖关系。 maven的依赖管理依赖管理一般是最吸引人使用maven的功能特性了,这个特性让开发者只需要关注代码的直接依赖,比如我们用了spring,就加入spring依赖说明就可以了,至于spring自己还依赖哪些外部的东西,maven帮我们搞定。 任意一个外部依赖说明包含如下几个要素:groupId, artifactId, version, scope, type, optional。其中前3个是必须的,各自含义如下:
maven认为,程序对外部的依赖会随着程序的所处阶段和应用场景而变化,所以maven中的依赖关系有作用域(scope)的限制。在maven中,scope包含如下的取值:
另外,代码有代码自己的依赖,各个maven使用的插件也可以有自己的依赖关系。依赖也可以是可选的,比如我们代码中没有任何cache依赖,但是hibernate可能要配置cache,所以该cache的依赖就是可选的。 多项目管理maven的多项目管理也是非常强大的。一般来说,maven要求同一个工程的所有子项目都放置到同一个目录下,每一个子目录代表一个项目,比如
按照这种格式存放,就是继承方式,所有具体子项目的pom.xml都会继承总项目pom的内容,取值为子项目pom内容优先。 要设置继承方式,首先要在总项目的pom中加入如下配置 <modules> <module>simple-weather</module> <module>simple-webapp</module> </modules> 其次在每个子项目中加入 <parent> <groupId>org.sonatype.mavenbook.ch06</groupId> <artifactId>simple-parent</artifactId> <version>1.0</version> </parent> 即可。 当然,继承不是唯一的配置文件共用方式,maven还支持引用方式。引用pom的方式更简单,在依赖中加入一个type为pom的依赖即可。 <project> <description>This is a project requiring JDBC</description> ... <dependencies> ... <dependency> <groupId>org.sonatype.mavenbook</groupId> <artifactId>persistence-deps</artifactId> <version>1.0</version> <type>pom</type> </dependency> </dependencies> </project> 属性用户可以在maven中定义一些属性,然后在其他地方用${xxx}进行引用。比如: <project> <modelVersion>4.0.0</modelVersion> ... <properties> <var1>value1</var1> </properties> </project>
maven提供了三个隐式的变量,用来访问系统环境变量、POM信息和maven的settings:
maven的profileprofile是maven的一个重要特性,它可以让maven能够自动适应外部的环境变化,比如同一个项目,在linux下编译linux的版 本,在win下编译win的版本等。一个项目可以设置多个profile,也可以在同一时间设置多个profile被激活(active)的。自动激活的 profile的条件可以是各种各样的设定条件,组合放置在activation节点中,也可以通过命令行直接指定。profile包含的其他配置内容可 以覆盖掉pom定义的相应值。如果认为profile设置比较复杂,可以将所有的profiles内容移动到专门的 profiles.xml 文件中,不过记得和pom.xml放在一起。 activation节点中的激活条件中常见的有如下几个:
maven的操作和使用maven的操作有两种方式,一种是通过mvn命令行命令,一种是使用maven的eclipse插件。因为使用eclipse的maven插件操作起来比较容易,这里就只介绍使用mvn命令行的操作。 maven的配置文件maven的主执行程序为mvn.bat,linux下为mvn.sh,这两个程序都很简单,它们的共同用途就是收集一些参数,然后用 java.exe来运行maven的Main函数。maven同样需要有配置文件,名字叫做settings.xml,它放在两个地方,一个是maven 安装目录的conf目录下,对所有使用该maven的用户都起作用,我们称为主配置文件,另外一个放在 %USERPROFILE%/.m2/settings.xml下,我们成为用户配置文件,只对当前用户有效,且可以覆盖主配置文件的参数内容。还有就是 项目级别的配置信息了,它存放在每一个maven管理的项目目录下,叫pom.xml,主要用于配置项目相关的一些内容,当然,如果有必要,用户也可以在 pom中写一些配置,覆盖住配置文件和用户配置文件的设置参数内容。 一般来说,settings文件配置的是比如repository库路径之类的全局信息,具体可以参考官方网站的文章 。 创建新工程要创建一个新的maven工程,我们需要给我们的工程指定几个必要的要素,就是maven产品坐标的几个要素:groupId, artifactId,如果愿意,你也可以指定version和package名称。我们先看一个简单的创建命令: d:\work\temp>mvn archetype:create -DgroupId=com.abc -DartifactId=product1 -DarchetypeArtifactId=maven-archetype-webapp 首先看这里的命令行参数的传递结构,怪异的 -D参数=值 的方式是 java.exe 要求的方式。这个命令创建一个web工程,目录结构是一个标准的maven结构,如下: D:. └─mywebapp │ pom.xml │ └─src └─main ├─resources └─webapp │ index.jsp │ └─WEB-INF web.xml 大家要注意,这里目录结构的布局实际上是由参数 archetypeArtifactId 来决定的,因为这里传入的是 maven-archetype-webapp 如果我们传入其他的就会创建不同的结构,默认值为 maven-archetype-quickstart ,有兴趣的读者可以参考更详细的列表 ,我把部分常用的列表在这里:
大家可以参考更详细的 archetype:create 帮助 和 archtype参考信息 。 maven的多项目管理多项目管理是maven的主要特色之一,对于一个大型工程,用maven来管理他们之间复杂的依赖关系,是再好不过了。maven的项目配置之间的关系有两种:继承关系和引用关系。 <modules> <module>ABCCommon</module> <module>ABCCore</module> <module>ABCTools</module> </modules>
要记住的是,这里的module是目录名,不是子工程的artifactId。子工程如下设置: <parent> <groupId>com.abc.product1</groupId> <artifactId>abc-product1</artifactId> <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>abc-my-module2</artifactId> <packaging>jar</packaging>
这样两者就相互关联起来了,继承关系就设定完毕,所有父工程的配置内容都会自动在子工程中生效,除非子工程有相同的配置覆盖。如果你不喜欢层层递进的目录结构来实现继承,也可以在parent中加入 <relativePath>../a-parent/pom.xml</relativePath> 来制定parent项目的相对目录。继承关系通常用在项目共同特性的抽取上,通过抽取公共特性,可以大幅度减少子项目的配置工作量。 引用关系是另外一种复用的方式,maven中配置引用关系也很简单,加入一个 type 为 pom 的依赖即可。 <dependency> <groupId>org.sonatype.mavenbook</groupId> <artifactId>persistence-deps</artifactId> <version>1.0</version> <type>pom</type> </dependency>
但是无论是父项目还是引用项目,这些工程都必须用 mvn install 或者 mvn deploy 安装到本地库才行,否则会报告依赖没有找到,eclipse编译时候也会出错。 需要特别提出的是复用过程中,父项目的pom中可以定义 dependencyManagement 节点,其中存放依赖关系,但是这个依赖关系只是定义,不会真的产生效果,如果子项目想要使用这个依赖关系,可以在本身的 dependency 中添加一个简化的引用 <dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> </dependency>
这种方法可以避免版本号满天飞的情况。 安装库文件到maven库中在maven中一般都会用到安装库文件的功能,一则是我们常用的hibernate要使用jmx库,但是因为sun的license限制,所以无法将其直接包含在repository中。所以我们使用mvn命令把jar安装到我们本地的repository中 mvn install:install-file -DgroupId=com.sun.jdmk -DartifactId=jmxtools -Dversion=1.2.1 -Dpackaging=jar -Dfile=/path/to/file 如果我们想把它安装到公司的repository中,需要使用命令 mvn deploy:deploy-file -DgroupId=com.sun.jdmk -DartifactId=jmxtools -Dversion=1.2.1 -Dpackaging=jar -Dfile=/path/to/file -Durl=http://aaa.ss.com/ss.xxx -DrepositoryId=release-repo 对于我们的工程输出,如果需要放置到公司的repository中的话,可以通过配置pom来实现 <distributionManagement> <repository> <id>mycompany-repository</id> <name>MyCompany Repository</name> <url>scp://repository.mycompany.com/repository/maven2</url> </repository> </distributionManagement>
这里使用的scp方式提交库文件,还有其他方式可以使用,请参考faq部分。然后记得在你的settings.xml中加入这一内容 <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> ... <servers> <server> <id>mycompany-repository</id> <username>jvanzyl</username> <!-- Default value is ~/.ssh/id_dsa --> <privateKey>/path/to/identity</privateKey> <passphrase>my_key_passphrase</passphrase> </server> </servers> ... </settings>
maven的变量maven定义了很多变量属性,参考这里 http://docs.codehaus.org/display/MAVENUSER/MavenPropertiesGuide
maven的使用我们已经知道maven预定义了许多的阶段(phase),每个插件都依附于这些阶段,并且在进入某个阶段的时候,调用运行这些相关插件的功能。我们先来看完整的maven生命周期:
maven核心的插件列表可以参考 http://maven.apache.org/plugins/index.html 。这里仅列举几个常用的插件及其配置参数:
maven的使用问答除了以下的几个faq条目之外,还有一些faq可以参考 兄弟们如果有其他问题,欢迎跟帖提问! 依赖关系问:如何增加删除一个依赖关系?答:直接在pom文件中加入一个dependency节点,如果要删除依赖,把对应的dependency节点删除即可。 问:如何屏蔽一个依赖关系?比如项目中使用的libA依赖某个库的1.0版,libB以来某个库的2.0版,现在想统一使用2.0版,如何去掉1.0版的依赖?答:设置exclusion即可。 <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> <version>3.2.5.ga</version> <exclusions> <exclusion> <groupId>javax.transaction</groupId> <artifactId>jta</artifactId> </exclusion> </exclusions> </dependency>
问:我有一些jar文件要依赖,但是我又不想把这些jar去install到mvn的repository中去,怎么做配置?答:加入一个特殊的依赖关系,使用system类型,如下: <dependency> <groupId>com.abc</groupId> <artifactId>my-tools</artifactId> <version>2.5.0</version> <type>jar</type> <scope>system</scope> <systemPath>${basedir}/lib/mylib1.jar</systemPath> </dependency> 但是要记住,发布的时候不会复制这个jar。需要手工配置,而且其他project依赖这个project的时候,会报告警告。如果没有特殊要求,建议直接注册发布到repository。 问:在eclipse环境中同时使用maven builder和eclipse builder,并且设置项目依赖关系之后,为什么编译会出现artifact找不到错误,但是直接使用命令行mvn构建则一切正常?答:在project属性中去掉java build path中对其他 project 的依赖关系,直接在pom中设置依赖关系即可 <!-- 依赖的其他项目 --> <dependency> <groupId>com.abc.project1</groupId> <artifactId>abc-project1-common</artifactId> <version>${project.version}</version> </dependency> 另外,保证没有其他错误。 问:我想让输出的jar包自动包含所有的依赖答:使用 assembly 插件即可。 <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> </configuration> </plugin> 问:我的测试用例依赖于其他工程的测试用例,如何设置?答:maven本身在发布的时候,可以发布单纯的jar,也可以同时发布xxx-tests.jar和xxx-javadoc.jar(大家经常在repository中可以看到类似的东西)。我们自己的项目A要同时输出test.jar可以做如下的设置 <!-- 用于把test代码也做成一个jar --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <executions> <execution> <goals> <goal>test-jar</goal> </goals> </execution> </executions> </plugin> 然后在其他需要引用的工程B中做如下的dependency设置 <dependency> <groupId>com.abc.XXX</groupId> <artifactId>工程A</artifactId> <version>${project.version}</version> <type>test-jar</type> <scope>test</scope> </dependency>
变量问:如何使用变量替换?项目中的某个配置文件比如jdbc.properties使用了一些pom中的变量,如何在发布中使用包含真实内容的最终结果文件?答:使用资源过滤功能,比如: <project> .. <properties> <jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName> <jdbc.url>jdbc:mysql://localhost:3306/development_db</jdbc.url> <jdbc.username>dev_user</jdbc.username> <jdbc.password>s3cr3tw0rd</jdbc.password> </properties> .. <build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> .. <profiles> <profile> <id>production</id> <properties> <jdbc.driverClassName>oracle.jdbc.driver.OracleDriver</jdbc.driverClassName> <jdbc.url>jdbc:oracle:thin:@proddb01:1521:PROD</jdbc.url> <jdbc.username>prod_user</jdbc.username> <jdbc.password>s00p3rs3cr3t</jdbc.password> </properties> </profile> </profiles> </project> 问: maven-svn-revision-number-plugin 插件说明答: maven-svn-revision-number-plugin 可以从 SVN 中获取版本号,并将其变成环境变量,交由其他插件或者profile使用,详细帮助在这里 。一般和resource的filter机制同时使用 <plugins> <plugin> <groupId>com.google.code.maven-svn-revision-number-plugin</groupId> <artifactId>maven-svn-revision-number-plugin</artifactId> <version>1.3</version> <executions> <execution> <goals> <goal>revision</goal> </goals> </execution> </executions> <configuration> <entries> <entry> <prefix>prefix</prefix> </entry> </entries> </configuration> </plugin> </plugins> 这段代码负责把resource文件中的内容替换成适当内容 repository = ${prefix.repository} path = ${prefix.path} revision = ${prefix.revision} mixedRevisions = ${prefix.mixedRevisions} committedRevision = ${prefix.committedRevision} status = ${prefix.status} specialStatus = ${prefix.specialStatus} 编译问:如何给插件指派参数?比如我要设置一些编译参数答:以下内容设定编译器编译java1.5的代码 <project> ... <build> ... <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> </plugins> ... </build> ... </project> 要设置其他插件的参数也可以,请参考对应插件的帮助信息 问:我的目录是非标准的目录结构,如何设置让maven支持?答:指定source目录和test-source目录即可。 <build> <directory>target</directory> <sourceDirectory>src</sourceDirectory> <scriptSourceDirectory>js/scripts</scriptSourceDirectory> <testSourceDirectory>test</testSourceDirectory> <outputDirectory>bin</outputDirectory> <testOutputDirectory>bin</testOutputDirectory> </build> 这个例子把源代码设置成了src目录,测试代码在test目录,所以输出到bin目录。这里要注意,directory如果也设置成bin目录的 话,maven打包的时候会引起死循环,因为directory是所有工作存放的地方,默认包含outputDirectory定义的目录在内。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-06-28
非常棒的一篇文章 常用问题解答非常有帮助
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-06-29
总结的很好,平时项目使用,对于maven的配置理解的还真不多,学习了。
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-06-29
我纠正一下LZ的发音吧,[ˈmeɪvən]
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-06-29
国内出了一本《maven实战》,看官方文档太累了
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-09-27
正在学习中,希望对自己有帮助
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-10-14
楼主 请教一下
就是如何把eclipse 和maven 结合起来 ? 如果web项目lib中 不放入jar 包的话。 写jave程序时 如何给提示? 我对maven 确实不知道怎么搞。谢谢。可以给我载email: to tangdu0228yes@163.com |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-10-14
tangduDream 写道 楼主 请教一下
就是如何把eclipse 和maven 结合起来 ? 如果web项目lib中 不放入jar 包的话。 写jave程序时 如何给提示? 我对maven 确实不知道怎么搞。谢谢。可以给我载email: to tangdu0228yes@163.com 先在命令行下执行 mvn -Declipse.workspace=<path-to-eclipse-workspace> eclipse:add-maven-repo 其中<path-to-eclipse-workspace>是你eclipse工作空间的路径 然后有两种做法: 1. 装了eclipse的maven plugin(eclipse 3.6好像自带,忘了)后,可以直接在eclipse里导入maven project。 或者 2. 在你maven项目的pom.xml目录上执行mvn eclipse:eclipse,就会把你当前的maven项目变成一个eclipse项目,然后再把它导入eclipse就可以了。(也可以先导入,再转换,然后在eclipse里刷新项目) 任何一种方法,都会自动帮你配好类路径和自动下载相关的jar包。你刷新一下项目,再重启一下eclipse,就能有提示了。 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-11-22
我们现在的项目需求是把某几个文件夹单独打包到一个jar文件,并且把这个文件夹放到指定的项目目录,这个用maven怎么实现
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
发表时间:2011-11-23
正在学习这个
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
返回顶楼 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||