maven:assembly打包插件简记

之前记录了maven:jar、dependency打包插件简记,这里再记录一下 maven-assembly打包插件的使用,方便日后回顾和查阅。

maven-assembly-plugin

assembly 也是 maven 下的一个打包插件,其可以将项目里的资源按照相应的配置(需要配置相应的 descriptor 描述文件)打包成一个包(支持 zip、jar、tar、tar.gz、tar.bz2包),其 pom 的配置和解释如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<!-- maven-assembly-plugin 自定义打包貌似无法打可执行 Jar,这里用 maven-jar-plugin 来打可执行jar包-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<useUniqueVersions>false</useUniqueVersions>
<mainClass>com.chifuyong.TestDemo</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>dependencies/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<!-- maven-assembly-plugin 打包配置,使用自定义文件描述来打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>assembly-test</id>
<!-- 在 package 阶段执行 assembly:single -->
<phase>package</phase>
<goals>
<!-- 在 package 阶段执行 assembly:single -->
<goal>single</goal>
</goals>
<configuration>
<!-- 打包后的文件名会以 finalName-id (id 为 descriptor xml 的 id ) -->
<finalName>${project.artifactId}</finalName>
<descriptors>
<!-- 自定义描述文件(里面定义了如何打包)的路径 -->
<descriptor>assemblies/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
<!-- 如果还需要打另一个以不同方式打的包,可以再配置一个 execution -->
</executions>
</plugin>

自定义描述文件 vs 内置描述文件

这里使用了 jar-plugin 来将项目打包成可执行 Jar,再通过 pom.xml 下的 <descriptor> 标签配置的描述文件 ,对项目里的资源进行整合打包成一个包文件,此次示例中用到的描述文件为:assemblies/assembly.xml ,其具体配置和解释如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<!-- maven-assembly-plugin 自定义打包配置-->
<id>${project.version}</id>
<formats>
<!--打包的类型:zip、jar、tar、tar.gz、tar.bz2、war、dir-->
<format>tar.gz</format>
</formats>
<!-- 打包后有无根路径目录,这边为true,
根路径目录为 pom 文件中的<finalName>${project.artifactId}</finalName> -->
<includeBaseDirectory>true</includeBaseDirectory>
<!-- 打包单个文件 -->
<files>
<file>
<!-- 把项目 jar 打包进去,并改名 -->
<source>${project.build.directory}/${project.artifactId}-${project.version}.jar</source>
<outputDirectory>/</outputDirectory>
<!-- 可以修改打包后文件的名称-->
<destName>maven-plugin-example.jar</destName>
</file>
</files>
<!--打包文件集-->
<fileSets>
<fileSet>
<!-- 文件目录 -->
<directory>${project.basedir}/src/main/resources/bin</directory>
<!-- 目标目录 -->
<outputDirectory>/</outputDirectory>
</fileSet>
<!-- config文件打包 -->
<fileSet>
<!-- ${profile.env} 为自定义的 profile -->
<directory>${project.basedir}/src/main/resources/config/${profile.env}</directory>
<outputDirectory>/conf</outputDirectory>
<includes>
<include>*.xml</include>
</includes>
</fileSet>
</fileSets>
<!--打包依赖库-->
<dependencySets>
<dependencySet>
<!-- 依赖所属目录 -->
<outputDirectory>/lib</outputDirectory>
<!--是否把包解开,默认为 false-->
<unpack>false</unpack>
<!-- 排除自身 -->
<useProjectArtifact>false</useProjectArtifact>
<!-- scope 范围-->
<scope>runtime</scope>
</dependencySet>
</dependencySets>
</assembly>

mvn:package 之后,打包后的会生成一个 *.tar.gz 文件,这个包里的文件就是按照描述里的配置而打包出来的,具体内容如下:

maven-assembly-plugin

maven-assembly-plugin

内置描述文件对比

描述文件输出格式包含内容适用场景
jar-with-dependenciesjar项目代码 + 所有依赖解包合并生成单个可执行 uber-jar
bintar.gz / zip项目 jar + 依赖 jar + 脚本生成可执行分发包(Linux)
srctar.gz / zip源码和资源文件分发源码包
projecttar.gz / zip项目构建输出分发构建产物

使用内置描述文件打包

默认的话 assembly 也有四个内置的 assembly descriptor 可以使用,在 maven-assembly-plugin.3.2.0.jar 下可以看到,相应的描述文件及其作用,如下图 bin.xml、jar-with-dependencies.xml 、src.xml、project.xml 都是其内置的描述文件,可以点击查看其相应的配置。

maven-assembly-plugin

如果想用内置描述文件进行打包也可以,这里用 jar-with-dependencies.xml (将项目代码和其所依赖的所有 jar 都打包到一个 jar 里)这个内置描述文件做例子,其配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- maven-assembly-plugin 打包配置:jar-with-dependencies -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.chifuyong.TestDemo</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

打包后的 jar 进行反编译,内容如下:

maven-assembly-plugin

常见问题排查

1. Could not find goal single in plugin

maven-assembly-plugin 的 goal 必须通过 single 而不是 assembly 调用。正确写法:

1
<goal>single</goal>

2. 打包后文件名包含 assembly id

默认情况下打包产物名称为 finalName-descriptorId 格式。若想去掉后缀,需设置:

1
<appendAssemblyId>false</appendAssemblyId>

3. 自定义描述文件找不到

描述文件路径相对于项目根目录(即 pom.xml 所在目录)。确认文件存在于正确路径:

1
${project.basedir}/assemblies/assembly.xml

4. 打包后缺少依赖

检查 dependencySet 中的 scope 配置:

  • runtime:包含 compile 和 runtime 作用域的依赖
  • compile:仅包含 compile 作用域的依赖
  • 如需包含所有依赖,使用 compile+runtime

5. Linux 下脚本文件没有执行权限

打包后解压 tar.gz 发现 .sh 脚本没有可执行权限,需在 fileSet 中添加:

1
<fileMode>0755</fileMode>