Maven
Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model(POM), Maven can manage a project’s build, reporting and documentation from a central piece of information.
参考文档:Maven Documentation
Maven概述
一个基本的Pom文件
<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>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Pom文件是面向工程的一个管理模型,全称是Project Object Model。这个Pom文件中包含的基本内容有:
- project pom文件的顶层元素
- modelVersion Pom对象模型的版本
- groupId 是创建这个项目的组织或部门的唯一标志,比如说
org.apache.maven.plugins
就是所有Maven plugins的groupId - artifactId 是这个项目生成结果的唯一标志,Maven生成结果的命名模式为
<artifactId>-<version>.<extension>
,比如说my app-1.0.jar
- packaging 这个参数表明了项目生成结果的打包模式,比如JAR,WAR,EAR等,同时这个参数还表明了build过程采用的特定生命周期
- version 这个参数表明了项目生成结果的版本,在version里经常会看到SNAPSHOT标志,它表明了项目处于开发阶段。
- name 这个参数代表项目的展示名字,通常作用在Maven生成的文档中
- url 这个参数代表哪里可以找到该项目,通常作用在Maven生成的文档中
- description 这个参数描述了项目的基本信息,通常作用在Maven生成的文档中
Maven项目的基本结构
my-app
|-- pom.xml
`-- src
|-- main
| `-- java
| `-- com
| `-- mycompany
| `-- app
| `-- App.java
`-- test
`-- java
`-- com
`-- mycompany
`-- app
`-- AppTest.java
上面是一个Maven项目的基本结构,项目的相关资源位于${basedir}/src/main/java
中,而测试的资源位于${basedir}/src/test/java
中,而pom文件位于pom.xml
中。
Maven的执行
1. mvn compile
执行mvn compile
,编译的结果会默认放在${basedir}/target/classes
目录下。
2. mvn test
执行mvn test
,会执行${basedir}/src/test/java
中的单元测试。如果只想编译测试代码而不执行,则执行mvn test-compile
。
3. mvn package
执行mvn package
会对项目进行打包,假如当前在pom中的packaging设定为jar,那么执行该命令后会在${basedir}/target
目录下生成对应的jar包。
4. mvn install
如果想把mvn package
生成的Jar文件安装在本地库中以让其它项目引用,则可以执行mvn install
命令,将生成的jar包放在${user.home}/.m2/repository
中。
Plugins
Plugins用来定制Maven项目的编译过程,假如要配置Java Compiler允许JDK 5.0的资源,那么只需要在Pom中增加如下内容:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
<configuration>
中的配置会应用在对应Plugin的所有Goal。
资源文件打包
${basedir}/src/main/resources
目录下的所有文件都会被打包到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
该项目打包成Jar文件后的内部组织结构为:
|-- META-INF
| |-- MANIFEST.MF
| |-- application.properties
| `-- maven
| `-- com.mycompany.app
| `-- my-app
| |-- pom.properties
| `-- pom.xml
`-- com
`-- mycompany
`-- app
`-- App.class
文件过滤
Maven支持文件过滤的功能,可以在build时候为文件提供变量赋值,比如说上面的application.properties
文件中有如下定义:
# application.properties
application.name=${project.name}
application.version=${project.version}
那么需要在pom文件中做如下的定义:
<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>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
执行mvn process-resources
命令后,在target/classes
下找到application.properties
可以看到如下结果:
# application.properties
application.name=Maven Quick Start Archetype
application.version=1.0-SNAPSHOT
可见其中形如${<property name>}
的变量已经被替换成了对应的值,如果要引入其它文件中定义的属性,只需要在pom文件中定义<filters>
,比如:
<build>
<filters>
<filter>src/main/filters/filter.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
那么Maven会先读出filter.properties
中的属性,然后把这些属性注入对应的resources中。
Dependencies
<dependencies>
标签下列出了所有的外部依赖,比如下面的Pom文件添加了Junit的依赖:
<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>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
<dependency>
的<scope>
标签的值可以为compile,test和runtime,当Maven编译项目时,它首先会在${user.home}/.m2/repository
这个本地库目录下寻找所需的依赖,如果没有会去远程的库上寻找,并将其下载到本地库中,默认的远程库地址为 http://repo.maven.apache.org/maven2/
。
包的发布
当需要发布一个包的远程仓库时,需要配置库的地址和相应的权限,一个范例如下:
<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>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
<build>
<filters>
<filter>src/main/filters/filters.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<!--
|
|
|
-->
<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>
多Modules管理
Maven很好的支持了多个Modules的管理,假如一个Maven项目结构如下:
+- pom.xml
+- my-app
| +- pom.xml
| +- src
| +- main
| +- java
+- my-webapp
| +- pom.xml
| +- src
| +- main
| +- webapp
对于根目录下的pom文件,内容如下:
<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>
其中的<modules>
定义了其管理的两个子modules。
假如my-webapp需要依赖my-app包,那么在my-webapp/pom.xml
中增加:
...
<dependencies>
<dependency>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
...
</dependencies>
然后在my-app和my-webapp的pom文件中都增加parent配置:
<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 clean install
,会创建my-webapp/target/my-webapp.war
,其中包含:
$ jar tvf my-webapp/target/my-webapp-1.0-SNAPSHOT.war
0 Fri Jun 24 10:59:56 EST 2005 META-INF/
222 Fri Jun 24 10:59:54 EST 2005 META-INF/MANIFEST.MF
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/
3239 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.xml
0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/
215 Fri Jun 24 10:59:56 EST 2005 WEB-INF/web.xml
123 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.properties
52 Fri Jun 24 10:59:56 EST 2005 index.jsp
0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/
2713 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/my-app-1.0-SNAPSHOT.jar
可见my-app-1.0-SNAPSHOT.jar
已经被放到了WEB-INF/lib
目录下。