12.2.2. 构建一个套件Building an Assembly

Assembly插件可以以两种方式运行:你可以直接在命令行调用,或者你可以通过绑定到生命周期阶段将其配置成标准构建过程的一部分。直接调用自有它的用处,主要是为了那些一次性,不属于你项目核心分发包的套件。大部分情况下,你可能以标准项目构建过程一部分的形式生成套件。这么做,不管你的项目被安装还是部署,都能包含你自定义的套件,从而它们也一直是对用户可用的。

作为一个直接调用Assembly插件的例子,考虑你想要将你的项目复制一份给别人让他们也能从源码构建。你需要同时包含源码,而不仅仅是一个最终的产品。而且你只是偶尔需要这么做,因此往你的POM中添加配置显得没有必要。你可以使用如下的命令:

$ mvn -DdescriptorId=project assembly:single 
...
[INFO] [assembly:single] 
[INFO] Building tar : /Users/~/mvn-examples-1.0/assemblies/direct-invocation/\
                      target/direct-invocation-1.0-SNAPSHOT-project.tar.gz 
[INFO] Building tar : /Users/~/mvn-examples-1.0/assemblies/direct-invocation/\
                      target/direct-invocation-1.0-SNAPSHOT-project.tar.bz2
[INFO] Building zip: /Users/~/mvn-examples-1.0/assemblies/direct-invocation/\
                      target/direct-invocation-1.0-SNAPSHOT-project.zip
...

假如你想要从你的项目生成一个可运行的JAR。如果你的项目完全是自包含的,没有任何依赖,那么使用JAR插件的archive配置就能做到。但是,大部分项目都有依赖,而且这些依赖需要被引入到可运行JAR文件中。这种情况下,每次JAR被安装或部署的时候你都要确认可运行JAR包含了这些依赖。

假设该项目的main类是org.sonatype.mavenbook.App,如下的POM配置将创建一个可运行的JAR

Example 12.1. 可运行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/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>org.sonatype.mavenbook.assemblies</groupId>
  <artifactId>executable-jar</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>Assemblies Executable Jar Example</name>
  <url>http://sonatype.com/book</url>
  <dependencies>
    <dependency>
      <groupId>commons-lang</groupId>
      <artifactId>commons-lang</artifactId>
      <version>2.4</version>
    </dependency>
  </dependencies>
 <build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.2-beta-2</version>
        <executions>
          <execution>
            <id>create-executable-jar</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
            <configuration>
              <descriptorRefs>
                <descriptorRef>
                  jar-with-dependencies
                </descriptorRef>
              </descriptorRefs>
              <archive>
                <manifest>
                  <mainClass>org.sonatype.mavenbook.App</mainClass>
                </manifest>
              </archive>
           </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

以上配置中有两点我们要注意。首先,我们不再像上次那样使用descriptorId参数,这里我们使用descriptorRefs配置。这样可以允许在同一次Assembly插件执行过程中使用多个套件类型,同时还能保持不要引入太多额外的配置。第二,configuration下的archive元素设置最终JAR的Main-Class manifest属性。该配置在所有创建JAR文件的插件中都很常见,如由默认打包类型使用的JAR插件。

现在,你可以通过执行mvn package生成可运行的JAR文件。之后,我们看一下target目录的内容,验证一下可运行JAR已经被生成了。最后,为了证明我们真的有可运行JAR了,那就运行一下吧。

$ mvn package
... (output omitted) ...
[INFO] [jar:jar]
[INFO] Building jar: /Users/~/mvn-examples-1.0/assemblies/executable-jar/target/\
                     executable-jar-1.0-SNAPSHOT.jar
[INFO] [assembly:single {execution: create-executable-jar}]
[INFO] Processing DependencySet (output=)
[INFO] Building jar: /Users/~/mvn-examples-1.0/assemblies/executable-jar/target/\
                     executable-jar-1.0-SNAPSHOT-jar-with-dependencies.jar
... (output omitted) ...
$ ls -1 target
... (output omitted) ...
executable-jar-1.0-SNAPSHOT-jar-with-dependencies.jar
executable-jar-1.0-SNAPSHOT.jar
... (output omitted) ...
$ java -jar \
        target/executable-jar-1.0-SNAPSHOT-jar-with-dependencies.jar 
Hello, World!

从以上的输出你可以看到,标准的项目构建现在生成了一个新的额外的构件。这个新的构件有一个名为jar-with-dependencies的分类器。最后,我们验证了这个新的JAR是可运行的,运行这个JAR会产生我们期望的输出“Hello, World!”。