使用maven构建多模块项目。在一个项目中使用多个模块的一个方法是将模块添加为依赖项,正常情况下,我们会添加一个外部模块作为依赖。但是,当模块是一个项目的一部分,并密切相关的时候,该项目应被构造为一个多模块项目。在一个多模块项目中,Maven可以确保所有子模块在主模块之前被构建。
我们的实例简单易懂:将一个获取指定格式的当前时间的方法拆分成两个子模块:app和util。util提供一个使用apache commons lang库格式化日期的静态方法,app模块依赖util模块打印格式化的日期。
(本文章分享在CSDN平台,更多精彩请阅读 东陆之滇的csdn博客:http://blog.csdn.net/zixiao217 ,如在其他平台看到此文可能会出现内容不完整的现象,请移至东陆之滇http://blog.csdn.NET/zixiao217查看原文)
首先,使用如下命令创建工程和模块目录:
-- create directory for top level project
$ mkdir multi-app
-- create directories for modules
$ cd multi-app
$ mkdir app
$ mkdir util
-- create source and test dir for util module
$ mkdir -p util/src/main/java/com/xyz/util
$ mkdir -p util/src/test/java/com/xyz/util
-- create source dir for app module
$ mkdir -p app/src/main/java/com/xyz
multi-app
目录作为多模块项目的顶层目录,它包含两个子模块:app
和util
。
多模块项目的顶层目录中需要包含一个pom.xml,multi-app/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/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.xyzgroupId>
<artifactId>multi-appartifactId>
<version>1.0version>
<packaging>pompackaging>
<modules>
<module>appmodule>
<module>utilmodule>
modules>
project>
在顶层POM中,我们定义了多模块项目的坐标和它的模块。顶层项目目录中仅仅包含一个pom.xml,并且打包类型为pom。modules/module
元素中,给多模块项目添加了两个子模块。顶层项目是父项目,它的坐标被正如我们接下来看到的,将会在子模块中引用。
你可能已经注意到了,在上面的模块定义中,我们将util放在app模块之后,但实际上util模块必须在app模块之前构建,因为app依赖于它。而在父模块(顶层模块)的pom.xml定义中使我们感到困惑的子模块构建顺序实际上会被mavan的一个反应堆(reactor)组件根据子模块的依赖合理安排它们的构建顺序。当我们构建multi-app时,reactor会先构建util再构建app。
util模块只有一个简单个DateUtil 类提供了一个静态发方法getToday()用来返回一个格式化的日期,也包含了一个测试方法。 multi-app/util/src/main/java/com/xyz/util/DateUtil.java
:
package com.xyz.util;
import java.util.Date;
import org.apache.commons.lang.time.DateFormatUtils;
public class DateUtil {
public static String getToday() {
String today = DateFormatUtils.format(new Date(), "dd-MMM-yyyy");
return today;
}
}
multi-app/util/src/test/java/com/xyz/util/DateUtilTest.java
:
package com.xyz.util;
import static org.junit.Assert.assertEquals;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.Test;
public class DateUtilTest {
@Test
public void testGetToday() {
String actual = DateUtil.getToday();
String expected = new SimpleDateFormat("dd-MMM-yyyy")
.format(new Date());
assertEquals(expected, actual);
}
}
util模块的pom.xml
定义了该模块的坐标和依赖,另外还使用了parent
元素包含了multi-app的坐标。 multi-app/util/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/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>com.xyzgroupId>
<artifactId>multi-appartifactId>
<version>1.0version>
parent>
<groupId>com.xyzgroupId>
<artifactId>utilartifactId>
<version>1.0version>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>commons-langgroupId>
<artifactId>commons-langartifactId>
<version>2.4version>
dependency>
dependencies>
project>
app模块仅仅包含一个App.java类依赖util模块输出格式化的日期。
multi-app/app/src/main/java/com/xyz/App.java
:
package com.xyz;
import com.xyz.util.*;
public class App {
public static void main(String[] args) {
System.out.println("Hello World! Today is " + DateUtil.getToday());
}
}
app模块的pom.xml定义了该模块的坐标,并且依赖了util模块,同样的将multi-app模块作为父模块。 multi-app/app/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/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>com.xyzgroupId>
<artifactId>multi-appartifactId>
<version>1.0version>
parent>
<groupId>com.xyzgroupId>
<artifactId>appartifactId>
<version>1.0version>
<dependencies>
<dependency>
<groupId>com.xyzgroupId>
<artifactId>utilartifactId>
<version>1.0version>
dependency>
dependencies>
project>
构建maven多模块项目,我们需要在顶层目录中运行build命令。可以这样构建 multi-app:
$ cd multi-app
$ mvn test
maven处理顶层POM文件multi-app/pom.xml
,它知道如何处理子模块 的POM文件app/pom.xml
和util/pom.xml
。一旦POM被处理,根据使用的模块反应堆构reactor建建立顺序依赖性并构建各模块。上述命令,maven首先执行multi-app的测试阶段(但是发现顶层项目并没有任何源码,不做任何事情)然后编译和测试util模块,最后编译和测试app模块。
对于mvn clean
命令,会按multi-app、util和app模块的顺序clean。 mvn install
命令编译、测试、打包、安装( compiles, tests, packages and installs)顺序是:multi-app、util 和app。
Assembly插件目的是提供一个把工程依赖元素、模块、网站文档等其他文件存放到单个归档文件里。
使用任何一个预定义的描述符你可以轻松的构建一个发布包。
而Maven多模块项目构建命令被执行,通常情况下,从项目的顶层目录开始,但是assembly 命令稍有不同。
在项目的顶层目录运行命令 assembly:assembly:
$ mvn assembly:assembly -DdescriptorId=project
为预先定义的描述符的src和bin,运行组件:组件的子模块的目录:
$ cd app
$ mvn assembly:assembly -DdescriptorId=src
$ cd ../util
$ mvn assembly:assembly -DdescriptorId=src
对于预定义描述符jar-with-dependencies,同样在app目录下执行assembly:assembly命令:
$ cd app
$ mvn assembly:assembly -DdescriptorId=jar-with-dependencies
POM中的pluginManagement元素允许在父POM中进行配置,所有子模块均可以继承这些配置。
假设multi-app的所有子模块均使用jdk1.8,一种方式是在app、util模块中的POM均配置编译插件。但是更好的方式是在顶层父模块中使用pluginManagement
元素,从而所有子模块均可继承插件配置。
multi-app/pom.xml
:
...
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-pluginartifactId>
<configuration>
<source>1.8source>
<target>1.8target>
configuration>
plugin>
plugins>
pluginManagement>
build>
...
当plugins/plugin元素直接在buile元素中使用的时候,插件定义会在当前POM生效。但是如果plugins/plugin元素是在pluginManagement元素中时,当前使用这种定义的POM位置并不会使用它,但是可以被子模块来继承配置生效。因此,multi-app的POM并不会使用maven-compiler-plugin插件指定的配置,而是会被app、util两个子模块继承使用。
戳这里下载项目源码: http://download.csdn.net/detail/zixiao217/9689359