使用maven-assembly-plugin如何打包多模块项目

 更新时间:2022年03月21日 14:03:40   作者:meaijojo  
这篇文章主要介绍了使用maven-assembly-plugin如何打包多模块项目,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

maven-assembly-plugin打包多模块项目

概述

maven-assembly-plugin 是目前maven项目中最常用的打包工具,它便利、配置简单,因此可以满足我们大部分的需求。

实际开发过程中大部分Maven项目都是多模块的,因为工作需要,对其进行了研究与尝试,目前可以将多模块按照自己需求打包到一起。

1. 需求

项目本身代码非常复杂,最深可以到三层模块,即GrandFather -> Parent -> child,要求打包后的结构如下:

​​​​

目录的含义不

再追溯,下面直接将打包方法。

2. 打包流程

2.1 新建打包模块

Maven多模块打包在一起时,需要新建一个专门用于打包的模块,该模块不需要有任何Java代码,只需要配置一些最终形成的环境即可。但是该模块有一个非常重要的要求: 该模块必须是整个项目最后一个进行打包的。

可以通过配置pom.xml中加载模块的顺序来控制,最后配置进入的即最后进行打包的:

本人项目比较复杂,最终配置的打包是在tools子模块下的tools-package模块中进行配置。

2.2 配置打包模块

根据最终生成的路径需求,将所有的相关路径及一些命令、配置文件等按照要求在打包模块中实现,放在resources目录即可。

注:该项目中不需要任何Java代码

2.3 配置打包模块的pom.xml

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4.1</version>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                        <configuration>
                            <finalName>xxxxx</finalName>
                            <descriptors>
                                <descriptor>src/main/resources/assemble/assemble.xml</descriptor>
                            </descriptors>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

2.4 配置其他模块打包方式

因为项目中使用的SpringBoot,SpringBoot也提供了一种打包方式:spring-boot-maven-plugin,这种方式打包时会将该项目中所有依赖的包(包括静态文件)统一打包至一个jar中,这个不是我们项目的需求,我们的需求是将所有的jar包(包括第三方及当前项目的jar包)都放在lib目录,且是单独存在。

因此需要将其他模块的打包配置修改,修改分为两步:

1)不再使用spring-boot-maven-plugin进行打包,即将其从pom.xml中删除;

2)在pom.xml文件中使用maven-jar-plugin进行打包,该打包如何配置请参考文章(待定)。

2.5 配置assemble.xml文件

assemble.xml文件中描述了具体如何打包,该打包过程和实际需求关系密切

<?xml version='1.0' encoding='UTF-8'?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0
                    http://maven.apache.org/xsd/assembly-1.1.0.xsd">
    <id>${project.version}</id>
    <formats>
        <format>tar.gz</format>
    </formats>
    <includeBaseDirectory>true</includeBaseDirectory>
    <moduleSets>
        <moduleSet>
            <useAllReactorProjects>true</useAllReactorProjects>
            <includes>
                <include>xxx.xx.x:base1</include>
                <include>xxx.xx.x:base2</include>
                <include>xxx.xx.x:base3</include>
                <include>xxx.xx.x:base4</include>
            </includes>
            <binaries>
                <outputDirectory>lib</outputDirectory>
                <unpack>false</unpack>
            </binaries>
        </moduleSet>
    </moduleSets>
    <fileSets>
        <fileSet>
            <directory>src/main/resources/bin</directory>
            <outputDirectory>bin</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>src/main/resources/conf</directory>
            <outputDirectory>conf</outputDirectory>
        </fileSet>
        <fileSet>
            <directory>src/main/resources/docs</directory>
            <outputDirectory>docs</outputDirectory>
        </fileSet><fileSet>
        <directory>src/main/resources/keys</directory>
        <outputDirectory>keys</outputDirectory>
    </fileSet>
        <fileSet>
            <includes>
                <include>README.md</include>
            </includes>
            <outputDirectory></outputDirectory>
        </fileSet>
    </fileSets>
    <dependencySets>
        <dependencySet>
            <unpack>false</unpack>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib</outputDirectory>
            <scope>provided</scope>
        </dependencySet>
        <dependencySet>
            <unpack>false</unpack>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib</outputDirectory>
            <scope>system</scope>
        </dependencySet>
        <dependencySet>
            <unpack>false</unpack>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib</outputDirectory>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>
</assembly>

具体的配置参数可以查看 https://maven.apache.org/plugins/maven-assembly-plugin/assembly.html

本人在实验过程中重点是处理了dependencySet这个配置:

<dependencySets>
        <dependencySet>
            <unpack>false</unpack>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib</outputDirectory>
            <scope>provided</scope>
        </dependencySet>
        <dependencySet>
            <unpack>false</unpack>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib</outputDirectory>
            <scope>system</scope>
        </dependencySet>
        <dependencySet>
            <unpack>false</unpack>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib</outputDirectory>
            <scope>runtime</scope>
        </dependencySet>
    </dependencySets>

请配置上上述三个部分,要不然总是会缺少一些依赖包打不进来,Mark一下,很重要!

使用maven-assembly-plugin插件来定制化打包

简单的说,maven-assembly-plugin 就是用来帮助打包用的,比如说打出一个什么类型的包,包里包括哪些内容等等。

目前至少支持以下打包类型:

  • zip
  • tar
  • tar.gz
  • tar.bz2
  • jar
  • dir
  • war

默认情况下,打jar包时,只有在类路径上的文件资源会被打包到jar中,并且文件名是${artifactId}-${version}.jar,下面看看怎么用maven-assembly-plugin插件来定制化打包。

首先需要添加插件声明:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.4</version>
    <executions>
        <execution>
            <!-- 绑定到package生命周期阶段上 -->
            <phase>package</phase>
            <goals>
                <!-- 绑定到package生命周期阶段上 -->
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

使用内置的Assembly Descriptor

要使用maven-assembly-plugin,需要指定至少一个要使用的assembly descriptor 文件。默认情况下,maven-assembly-plugin内置了几个可以用的assembly descriptor:

  • bin : 类似于默认打包,会将bin目录下的文件打到包中;
  • jar-with-dependencies : 会将所有依赖都解压打包到生成物中;
  • src :只将源码目录下的文件打包;
  • project : 将整个project资源打包。

要查看它们的详细定义,可以到maven-assembly-plugin-2.4.jar里去看,例如对应 bin 的assembly descriptor 如下:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
    <id>bin</id>
    <formats>
        <format>tar.gz</format>
        <format>tar.bz2</format>
        <format>zip</format>
    </formats>
    <fileSets>
        <fileSet>
            <directory>${project.basedir}</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>README*</include>
                <include>LICENSE*</include>
                <include>NOTICE*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>*.jar</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/site</directory>
            <outputDirectory>docs</outputDirectory>
        </fileSet>
    </fileSets>
</assembly>

自定义Assembly Descriptor

一般来说,内置的assembly descriptor都不满足需求,这个时候就需要写自己的assembly descriptor的实现了。先从一个最简单的定义开始:

<?xml version='1.0' encoding='UTF-8'?>
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0  
                    http://maven.apache.org/xsd/assembly-1.1.0.xsd">
    <id>demo</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/classes</directory>
            <outputDirectory>/</outputDirectory>
        </fileSet>
    </fileSets>
</assembly>

这个定义很简单:

  • format:指定打包类型;
  • includeBaseDirectory:指定是否包含打包层目录(比如finalName是output,当值为true,所有文件被放在output目录下,否则直接放在包的根目录下);
  • fileSets:指定要包含的文件集,可以定义多个fileSet;
  • directory:指定要包含的目录;
  • outputDirectory:指定当前要包含的目录的目的地。

要使用这个assembly descriptor,需要如下配置:

<configuration>  
    <finalName>demo</finalName>  
    <descriptors>
        <!--描述文件路径-->
        <descriptor>assemblies/demo.xml</descriptor>  
    </descriptors>  
    <outputDirectory>output</outputDirectory>
</configuration> 

最后会生成一个demo-demo.jar 文件在目录 output 下,其中前一个demo来自finalName,后一个demo来自assembly descriptor中的id,其中的内容和默认的打包出来的jar类似。

如果只想有finalName,则增加配置:

<appendAssemblyId>false</appendAssemblyId>  

添加文件

上面演示了添加所有编译后的资源,同样的可以增加其他资源,例如想添加当前工程目录下的某个文件 b.txt ,在assembly descriptor的assembly结点下增加

<files>
    <file>
        <source>b.txt</source>
        <outputDirectory>/</outputDirectory>
    </file>
</files>

这里用到了 files 元素类型,可以想象 fileSets 下的结点都是针对文件夹的;files 下的结点都是针对文件的。

也可以改变打包后的文件名,例如上面的 b.txt ,希望打包后的名字为 b.txt.bak, 只需要在file 里添加以下配置 :

<destName>b.txt.bak</destName>

排除文件

在 fileSet 里可以使用 includes 和 excludes 来更精确的控制哪些文件要添加,哪些文件要排除。

例如要排除某个目录下所有的txt文件:

<fileSet>  
    <directory>${project.build.directory}/classes</directory>  
    <outputDirectory>/</outputDirectory>  
    <excludes>  
        <exclude>**/*.txt</exclude>  
    </excludes>  
</fileSet>

或者某个目录下只想 .class 文件:

<fileSet>
    <directory>${project.build.directory}/classes</directory>
    <outputDirectory>/</outputDirectory>
    <includes>
        <include>**/*.class</include>
    </includes>
</fileSet>

添加依赖

如果想把一些依赖库打到包里,可以用 dependencySets 元素,例如最简单的,把当前工程的所有依赖都添加到包里:

<dependencySets>
    <dependencySet>
        <outputDirectory>/</outputDirectory>
    </dependencySet>
</dependencySets>

在assembly下添加以上配置,则当前工程的依赖和工程本身生成的jar都会被打包进来。

如果要排除工程自身生成的jar,则可以添加

<useProjectArtifact>false</useProjectArtifact>

unpack参数可以控制依赖包是否在打包进来时是否解开,例如解开所有包,添加以下配置:

<unpack>true</unpack>

和 fileSet 一样,可以使用 excludes 和 includes 来更详细的控制哪些依赖需要打包进来;另外 useProjectAttachments,useTransitiveDependencies,useTransitiveFiltering等参数可以对间接依赖、传递依赖进行控制。

其他选项

  • moduleSets:当有子模块时候用;
  • repositories:想包含库的时候用;
  • containerDescriptorHandlers:可以进行一些合并,定义ArtifactHandler之类的时候可以用,(可以参考:说明);
  • componentDescriptors:如上所述,可以包含一些componentDescriptor定义,这些定义可以被多个assembly共享。

Assembly Plugin更多配置

上面已经看到了一些Assembly Plugin本身的配置,例如 finalName, outputDirectory, appendAssemblyId 和 descriptors 等,除了这些还有其他的一些可配置参数,参见:single,其中某些参数会覆盖在assembly descriptor 中的参数。有一个比较有用的参数是: archive,它的详细配置在:archive。

下面介绍一些archive的用法。

指定Main-Class

archive的一个重要用处就是配置生成的MANIFEST.MF文件。默认会生成一个MANIFEST.MF文件,不过这个文件默认值没什么意义。如果想指定生成jar的Main-Class,可以如下配置:

<archive>  
    <manifest>  
        <mainClass>demo.DemoMain</mainClass>  
    </manifest>  
</archive>

下面来看一个项目中实际配置的文件:

pom文件:

<plugin>                                                                
    <groupId>org.apache.maven.plugins</groupId>                         
    <artifactId>maven-assembly-plugin</artifactId>                      
    <version>${maven-assembly-plugin.version}</version>                                          
    <configuration>                                                     
        <descriptors>                                                   
            <descriptor>package.xml</descriptor>                        
        </descriptors>                                                  
    </configuration>                                                    
    <executions>                                                        
        <execution>                                                     
            <id>make-assembly</id>                                      
            <phase>package</phase>                                      
            <goals>                                                     
                <goal>single</goal>                                     
            </goals>                                                    
        </execution>                                                    
    </executions>                                                       
</plugin>  

assembly descriptor 文件:

<assembly>
    <id>${assembly-id}</id>
    <!-- 最终打包成一个用于发布的war文件 -->
    <formats>
        <format>${assembly-format}</format>
    </formats>
    <fileSets>
        <!-- 把项目公用的配置文件,打包进zip文件的config目录 -->
        <fileSet>
            <directory>${project.basedir}/src/main/resources/base</directory>
            <outputDirectory>WEB-INF/classes</outputDirectory>
        </fileSet>
        <!-- 把项目环境的配置文件,打包进zip文件的config目录 -->
        <fileSet>
            <directory>${project.basedir}/src/main/resources/${env}</directory>
            <outputDirectory>WEB-INF/classes</outputDirectory>
        </fileSet>
        <!-- 打包项目自己编译出来的jar文件 -->
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>WEB-INF/lib</outputDirectory>
            <includes>
                <include>*.jar</include>
            </includes>
        </fileSet>
        <!-- 打包项目依赖的jar文件 -->
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>WEB-INF/lib/*.jar</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java实现序列化与反序列化的简单示例

    Java实现序列化与反序列化的简单示例

    序列化与反序列化是指Java对象与字节序列的相互转换,一般在保存或传输字节序列的时候会用到,下面有两个Java实现序列化与反序列化的简单示例,不过还是先来看看序列和反序列化的具体概念:
    2016-05-05
  • Spring将MultipartFile转存到本地磁盘的三种方式

    Spring将MultipartFile转存到本地磁盘的三种方式

    在Java中处理文件向来是一种不是很方便的操作,然后随着Spring框架的崛起,使用Spring框架中的MultipartFile来处理文件也是件很方便的事了,今天就给大家介绍Spring将MultipartFile转存到本地磁盘的方式,需要的朋友可以参考下
    2024-10-10
  • SpringBoot关于自动注入mapper为空的坑及解决

    SpringBoot关于自动注入mapper为空的坑及解决

    这篇文章主要介绍了SpringBoot关于自动注入mapper为空的坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • hibernate一对多关联映射学习小结

    hibernate一对多关联映射学习小结

    这篇文章主要介绍了hibernate一对多关联映射学习小结,需要的朋友可以参考下
    2017-09-09
  • Java基于final修饰数据过程解析

    Java基于final修饰数据过程解析

    这篇文章主要介绍了Java基于final修饰数据过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • 一道关于java异常处理的题目

    一道关于java异常处理的题目

    本文给大家分享一道关于java异常处理的题目,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09
  • Java基础教程之八大基本数据类型

    Java基础教程之八大基本数据类型

    这篇文章主要给大家介绍了关于Java基础教程之八大基本数据类型的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • 解决spring-boot-starter-web等报红问题

    解决spring-boot-starter-web等报红问题

    这篇文章主要介绍了解决spring-boot-starter-web等报红问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Java中java.sql.SQLException异常的正确解决方法(亲测有效!)

    Java中java.sql.SQLException异常的正确解决方法(亲测有效!)

    SQLException是在Java中处理数据库操作过程中可能发生的异常,通常是由于底层数据库操作错误或违反了数据库规则而引起的,下面这篇文章主要给大家介绍了关于Java中java.sql.SQLException异常的正确解决方法,需要的朋友可以参考下
    2024-01-01
  • Java删除指定文件夹下的所有内容的方法(包括此文件夹)

    Java删除指定文件夹下的所有内容的方法(包括此文件夹)

    下面小编就为大家带来一篇Java删除指定文件夹下的所有内容的方法(包括此文件夹) 。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12

最新评论