Apache Maven是一个项目管理和自动构建工具,依赖于项目对象模型(pom),maven可以通过一段中心信息配置来管理项目的构建、发布和文档。
Maven,这个意第绪语的单词意味着“知识的积累”,最初在Jakarta Turbine 项目上,用于尝试去简化构建项目的过程。有几个项目,他们分别有他们区别微小的ant文件和jar文件,这些文件放在cvs中。我们想用一种标准的方式构建这些项目,有一个清晰的项目组成定义,一种简单的发布项目信息的方法,以及在几个项目中分享jar文件的方法。
这样的结果就是产生了一个工具--maven,它用于构建和管理java项目。我们希望我们创造的东西能让java开发者一天一天的工作变的简单,并且让java项目更加容易理解。
以上是maven官网对maven的介绍,我翻译的不怎么样,大概就是这么个意思。其中提到与ant的区别,指出了maven相对于ant的优势所在。
根据官网的介绍,我们做一个小例子,共同学习一下maven:
一下载安装maven
地址:http://maven.apache.org/download.cgi。另外你需要安装JDK(1.5或1.5以上),因为maven是一个java工具,jre不能满足需要。
对于window系统,需要设置环境变量。
1.设置 M2_HOME 变量,这个变量的值为maven的解压目录。例如解压目录为:C:\Program Files\Apache Software Foundation\apache-maven-3.1.0,那么M2_HOME的value就是此路径,当然此路径中不能包含空格。注意:对于 Maven2.0.9,路径的最后一个字符不能是'\'。
2.设置 M2变量,值为: %M2_HOME%\bin;
3.(可选的)设置MAVEN_OPTS变量,它用于设置jvm的属性,例如 -Xms256m -Xmx512m.这个属性可以给maven提供额外的选则;
4.设置path变量,将 %M2_HOME%\bin添加到path变量值的后边,记得要与之前的值用";"隔开;
5.确保设置了JAVA_HOME,以及将 %JAVA_HOME%\bin设置到path中;
6.运行mvn -version命令,查看maven是否安装成;
出现如此信息后,表示maven按装成功。
二.设置maven
maven的配置有三个级别:
Project 大多数静态的配置在pom.xml文件中;
Installation 这个配置在maven安装的时候添加一次;
User 这个配置用于特定的用户;
我们可以配置User配置在 ${user.home}/.m2/settings.xml文件中,这个settings.xml文件可以从% M2_HOME%\conf目录中拷贝一个。
% M2_HOME%\conf下的settings.xml文件用于配置全局的行为,${user.home}/.m2/settings.xml用于配置该用户的行为;
1.配置本地仓库
本地仓库的位置可以在user配置中修改,默认的仓库位置是${user.home}/.m2/repository/
<settings>
...
<localRepository>/path/to/local/repo/</localRepository>
...
</settings>
注意:这个仓库位置必须是绝对路径;
2 设置proxy
默认情况下不需要设置;需要设置的话可以参照:http://maven.apache.org/guides/mini/guide-proxies.html
三.创建项目
1.生成项目:
打开命令行,执行命令:
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DgroupId=com.mycompany.app -DartifactId=my-app
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
project
:他是pom.xml文件的顶级元素;
my-app
|-- pom.xml
`-- src
|-- main
| `-- java
| `-- com
| `-- mycompany
| `-- app
| `-- App.java
`-- test
`-- java
`-- com
`-- mycompany
`-- app
`-- AppTest.java
integration-test:如有需要,将包处理和发布到一个能够进行集成测试的环境。
verify:运行所有检查,验证包是否有效且达到质量标准。
Deploy:在集成或者发布环境下执行,将最终版本的包拷贝到远程的repository,使得其他的开发者或者工程可以共享。
clean: 删除target 目录;
eclipse:eclipse: 这个用于将工程转换为eclipse工程。
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
..
在你指定插件版本的情况下,插件会自动的下载和使用。查看哪些插件是有用的,可以查看:
http://maven.apache.org/plugins/.学习如何配置插件,查看:
http://maven.apache.org/guides/mini/guide-configuring-plugins.html
五.添加资源到生成的jar文件中
my-app
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mycompany
| | `-- app
| | `-- App.java
| `-- resources
| `-- META-INF
| `-- application.properties
`-- test
`-- java
`-- com
`-- mycompany
`-- app
`-- AppTest.java
在上面的例子中,我们添加了
${basedir}/src/main/resources目录,用于存放将会被打包的资源。maven规定:放在 ${basedir}/src/main/resources目录的资源文件会被打包,结构与生成jar文件开始部分相同。(any directories or files placed within the ${basedir}/src/main/resources directory are packaged in your JAR with the exact same structure starting at the base of the JAR.)。上面的文档结构中将资源文件放在了META-INF下,也可以直接放在resources下。
META-INF
| |-- MANIFEST.MF
| |-- application.properties
| |-- maven
| `-- com.mycompany.app
| `-- my-app
| |-- pom.properties
| `-- pom.xml
`---- com
`-- mycompany
`-- app
`-- App.class
正如你看到的,
${basedir}/src/main/resources
路径下的内容在jar文件的基本路径下被找到, application.properties在META-INF路径下。另外,你会发现 META-INF/MANIFEST.MF,pom.xml 和 pom.properties,这些文件是maven生成jar包的标准结构。pom.xml 和 pom.properties被打包是为了让每个maven生产的产品都是自描述的,并且允许你利用这些元信息。一个很简单的用途是能够检索应用的版本。直接操作pom.xml会很复杂,而properties文件很方便。
my-app
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mycompany
| | `-- app
| | `-- App.java
| `-- resources
| `-- META-INF
| |-- application.properties
`-- test
|-- java
| `-- com
| `-- mycompany
| `-- app
| `-- AppTest.java
`-- resources
`-- test.properties
在单元测试中,你可以通过以下方式获取资源文件:
...
// Retrieve resource
InputStream is = getClass().getResourceAsStream( "/test.properties" );
// Do something with the resource
...
六.过滤资源文件
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
根据以上的定义,资源文件需在:src/main/resource目录下,并且设置
filtering为true,它默认是false.我们定义这个资源文件的名称为:application.properties。内容为:
# application.properties
application.name=${pom.name}
application.version=${pom.version}
引用定义在
pom.xml文件中的属性,属性的名称要求是xml节点的名称,用“pom”作为根节点。例如{pom.name} 可以获得项目的名称,${pom.version}可以获得项目的版本,${pom.build.finalName}可以获得项目打包后最终生成文件的名称。pom.xml文件中一些节点有默认值,所以不需要去明确地定义它们的值。对于settings.xml文件,类似的它用"settings"作为根节点,例如 ${settings.localRepository}可以获得本地库的位置。
mvn process-resources 这个命令是在构建的生命周期中拷贝和过滤资源文件。
执行完成之后,找到target/classes下的application.properties文件,内容如下:
如果要获得外部文件的属性,你需要在pom.xml文件中添加对外部文件的引用。首先我们创建一个properties文件,src/main/filters/filter.properties# application.properties application.name=Maven Quick Start Archetype application.version=1.0-SNAPSHOT
在pom.xml文件中添加:# filter.properties my.filter.value=hello!
更改application.properties文件的内容如下:<build> <filters> <filter>src/main/filters/filter.properties</filter> </filters> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build>
重新执行mvn process-resources命令,找到target/classes下的application.properties文件,内容如下:# application.properties application.name=${pom.name} application.version=${pom.version} message=${my.filter.value}
这样就可以获得外部文件的属性。# application.properties application.name=Maven Quick Start Archetype application.version=1.0-SNAPSHOT message=hello!
如果不想通过外部文件,也可以在pom.xml文件中这样改:
可以达到同样的效果。<build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> <properties> <my.filter.value>hello</my.filter.value> </properties>
如果要获得系统属性,不管是获得系统的还是java的(例如 java.version 或 user.home),或者是通过java -D参数的形式传进的命令行参数,都可以。
再次修改application.properties文件:
执行命令: mvn process-resources "-Dcommand.line.prop=hello again",application.properties中的属性就会被赋值。# application.properties java.version=${java.version} command.line.prop=${command.line.prop}
七.使用外部依赖
pom.xml文件中的dependencies 节点列出了该项目需要的所有外部依赖。
以上代码表示工程只依赖 JUnit。<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies>
对于每个外部依赖,需要至少定义四个配置: groupId, artifactId, version, scope。这 groupId, artifactId, version需要和外部依赖中pom.xml中的信息相同,scope指明该项目如何使用这些依赖,它的值可以是 compile, test, 或runtime.。拥有这些外部依赖信息的配置,在构建工程时可以引用这些依赖。maven会从本地库中寻找这些依赖,如果找不到,就会从远程库中下载到本地库中。默认情况下,maven使用的远程库可以在http://search.maven.org/#browse找到。当然,你也可以设置自己的远程库,代替默认的。
现在项目需要用到log4j,那么自然需要增加对它的依赖,即log4j的jar包。在远程库中搜索“log4j”
找到一个合适的,打开pom.xml文件
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j</artifactId>
<version>2.0-beta9</version>
<scope>compile</scope>
</dependency>
</dependencies>
这样,log4j的依赖就添加完成了。在构建项目时,maven会自动从远程库中下载log4j的jar包。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>mycompany-repository</id>
<name>MyCompany Repository</name>
<url>scp://repository.mycompany.com/repository/maven2</url>
</repository>
</distributionManagement>
</project>
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> (default is ~/.ssh/id_dsa)
<passphrase>my_key_passphrase</passphrase>
</server>
</servers>
...
</settings>
如果在settings.xml文件中使用
passwords,应该注意。详细参见:http://maven.apache.org/guides/mini/guide-encryption.html
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-webapp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>my-webapp</finalName>
</build>
</project>
执行命令:
mvn clean package ,在target的目录下会生成my-webapp.war.
+- pom.xml
+- my-app
| +- pom.xml
| +- src
| +- main
| +- java
+- my-webapp
| +- pom.xml
| +- src
| +- main
| +- webapp
父类的pom.xml文件的内容:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>my-app</module>
<module>my-webapp</module>
</modules>
</project>
...
<dependencies>
<dependency>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
...
</dependencies>
在两个字项目中的pom.xml中添加:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>app</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
...
最后执行 mvn package命令,产生的war位置在
my-webapp/target/my-webapp.war。这样就完成了同时构建多个项目。