起这么一个使人困惑的名字是怎么回事?让我们建立这样一个能解释组装套件(assembling
assemblies)概念的场景。假设你想要创建一个归档,它包含了一些项目套件。再假设你有一个多模块构建,并且想要部署一个包含很多相关项目套件的套件。在本节的例子中,我们要为一组通常一起被使用的项目创建一个“可构建”的项目目录。为了简便,我们要重用前面讨论的两个project
和jar-with-dependencies
内置套件描述符。在这个特定的例子中,假设每个项目在主要的JAR构件之外还创建project
套件。假设这个多模块构建中每个项目都使用project
descriptorRef
绑定到package
阶段的single
目标。每个模块都会从顶层的pom.xml
中继承该配置,其pluginManagement
元素如Example 12.2, “在顶层POM中配置项目套件”所示:
Example 12.2. 在顶层POM中配置项目套件
<project> ... <build> <pluginManagement> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.2-beta-2</version> <executions> <execution> <id>create-project-bundle</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <descriptorRefs> <descriptorRef>project</descriptorRef> </descriptorRefs> </configuration> </execution> </executions> </plugin> </plugins> </pluginManagement> </build> ... </project>
每个项目的POM都使用很小的一部分插件声明引用了Example 12.2, “在顶层POM中配置项目套件”中的插件配置,如Example 12.3, “在子项目中激活Assembly插件配置”所示:
Example 12.3. 在子项目中激活Assembly插件配置
<build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> </plugin> </plugins> </build>
要生成一组项目套件,从顶层目录运行mvn install。你会看到Maven使用分类器将套件安装到你的本地仓库。
$ mvn install
...
[INFO] Installing ~/mvn-examples-1.0/assemblies/as-dependencies/project-parent/\
second-project/target/second-project-1.0-SNAPSHOT-project.tar.gz to
~/.m2/repository/org/sonatype/mavenbook/assemblies/second-project/1.0-SNAPSHOT/\
second-project-1.0-SNAPSHOT-project.tar.gz
...
[INFO] Installing ~/mvn-examples-1.0/assemblies/as-dependencies/project-parent/\
second-project/target/second-project-1.0-SNAPSHOT-project.tar.bz2 to
~/.m2/repository/org/sonatype/mavenbook/assemblies/second-project/1.0-SNAPSHOT/\
second-project-1.0-SNAPSHOT-project.tar.bz2
...
[INFO] Installing ~/mvn-examples-1.0/assemblies/as-dependencies/project-parent/\
second-project/target/second-project-1.0-SNAPSHOT-project.zip to
~/.m2/repository/org/sonatype/mavenbook/assemblies/second-project/1.0-SNAPSHOT/\\
second-project-1.0-SNAPSHOT-project.zip
...
当你运行install的时候,Maven会将每个项目的主构件和每个套件复制到你的本地Maven仓库中。现在本地的所有其它项目都可以使用依赖引用这些构件。如果你最终的目的是创建一个包含多个多模块项目构件的软件包,你可以创建一个项目,它以依赖的形式引入其它项目的套件。这个包裹项目(贴切的命名为project-bundle)负责创建一个最终的包裹套件。这个包裹项目的POM如Example 12.4, “套件包裹项目的POM”所示:
Example 12.4. 套件包裹项目的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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.sonatype.mavenbook.assemblies</groupId> <artifactId>project-bundle</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <name>Assemblies-as-Dependencies Example Project Bundle</name> <url>http://sonatype.com/book</url> <dependencies> <dependency> <groupId>org.sonatype.mavenbook.assemblies</groupId> <artifactId>first-project</artifactId> <version>1.0-SNAPSHOT</version> <classifier>project</classifier> <type>zip</type> </dependency> <dependency> <groupId>org.sonatype.mavenbook.assemblies</groupId> <artifactId>second-project</artifactId> <version>1.0-SNAPSHOT</version> <classifier>project</classifier> <type>zip</type> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.2-beta-2</version> <executions> <execution> <id>bundle-project-sources</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <descriptorRefs> <descriptorRef> jar-with-dependencies </descriptorRef> </descriptorRefs> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
该包裹项目的POM引用了来自于first-project
和second-project
的两个套件。这个POM指定了一个值为project
的分类器和一个值为zip
的类型,而不是直接引用过了项目的主构件。这告诉Maven去解析project
套件创建的ZIP归档。注意包裹项目生成了一个jar-with-dependencies
套件。jar-with-dependencies
并不创建一个非常简洁的套件,而是简单的创建一个包含所有依赖拆解内容的JAR文件。jar-with-dependencies
实际上做的事情是:告诉Maven拿来所有依赖,将其拆解,然后创建一个包含当前项目所有输出的归档。在这个项目中,它的效果就是创建一个带有first-project
和second-project
套件拆解内容的JAR文件,
该样例展示了如何不用自定义套件描述符就能联合Maven
Assembly插件的基本能力。它实现了创建一个包含多模块项目内容的单独归档这样一个目的。这个时候,jar-with-dependencies
仅仅是一个存储格式,因此我们没必要指定Main-Class
的manifest属性。我们只要正常的构建project-bundle
项目就能得到套件。
$ mvn package
...
[INFO] [assembly:single {execution: bundle-project-sources}]
[INFO] Processing DependencySet (output=)
[INFO] Building jar: ~/downloads/mvn-examples-1.0/assemblies/as-dependencies/\
project-bundle/target/project-bundle-1.0-SNAPSHOT-jar-with-dependencies.jar
要验证project-bundle套件是否包含了所有依赖套件的拆解内容,运行jar tf:
$ java tf \
target/project-bundle-1.0-SNAPSHOT-jar-with-dependencies.jar
...
first-project-1.0-SNAPSHOT/pom.xml
first-project-1.0-SNAPSHOT/src/main/java/org/sonatype/mavenbook/App.java
first-project-1.0-SNAPSHOT/src/test/java/org/sonatype/mavenbook/AppTest.java
...
second-project-1.0-SNAPSHOT/pom.xml
second-project-1.0-SNAPSHOT/src/main/java/org/sonatype/mavenbook/App.java
second-project-1.0-SNAPSHOT/src/test/java/org/sonatype/mavenbook/AppTest.java
阅读本节内容之后,标题应该容易理解了。我们使用了一个包裹项目,它依赖于两个项目的套件,然后我们再根据这两个项目的套件装配出一个最终的套件。