目录

零:说在前面

一:常用插件的介绍

二:常用插件的对比

三:打一个瘦jar包

        3.1:背景

        3.2:解决方案

四:插件应用举例

        4.1:maven-jar-plugin 举例及部分说明

       4.2:maven-dependency-plugin 举例及部分说明

        4.3:maven-resources-plugin 举例及部分说明

五:附录


零:说在前面

        Maven插件很多,但是本人感觉真正常用的有这么几个:spring-boot-maven-plugin、maven-jar-plugin、maven-resource-plugin、maven-dependency-plugin、maven-assembly-plugin。下面分别介绍并举例

一:常用插件的介绍

        1.1:spring-boot-maven-plugin

                负责将源码和依赖、以及springboot loader相关内容打成一个包。保证打出的包能独立运行。

        1.2:maven-jar-plugin

                仅负责将源码打成jar包,不能独立运行。另外,可以根据你的设置,将依赖jar包路径和程序的主入口定义在所打jar包中的 MANIFEST.MF 文件里。

        1.3:maven-dependency-plugin

                负责将各种依赖打包。也可以根据你的设置,将所打的依赖jar包输出到指定位置。

        1.4:maven-resource-plugin

                负责将正式与测试用到的资源文件导出到指定位置。还负责用资源文件中的参数替换pom文件中对应的占位符。
        1.5:maven-assembly-plugin

                负责打包。但是至少要指定需要打哪些内容,这个插件才能正常干活儿。

        1.6:maven-surefire-plugin

                负责测试。这一插件可以在maven的test阶段单独执行,在编译打包阶段可以被执行或跳过。可以指定其测试的范围或全量执行所有以Test开头或结尾的代码。

        

二:常用插件的对比

        2.1:spring-boot-maven-plugin 相当于 jar-plugin 和 dependency-plugin 的功能合成。与那两个插件相比,spring-boot-maven-plugin 会把springboot的一些个性化的内容打到包里。比如上面提到的 springboot loader 内容。

        2.2:maven-assembly-plugin 是基于 jar-plugin 和 dependency-plugin 的成果做了二次加工。它会把其他插件打出的jar包以及用户指定的额外项目也打入到成品之中。换言之,如果你用spring-boot-maven-plugin 搭配 maven-assembly-plugin 一起工作 和 maven-jar-plugin 搭配 maven-assembly-plugin 一起工作得到的产物会有不同。

三:打一个瘦jar包

        3.1:背景

        在Dev/Ops开发运维一体化思想大行其道的今天,技术部门对CI/CD的要求也变得越来越高。因此,docker等容器技术的普及也是势在必行。那么如何充分利用docker镜像的分层思想,提高镜像的复用程度,并减少每次生成镜像所花费的时间等问题,就需要我们深入思考。

        3.2:解决方案

        首先,可以将做一个三层的基础docker镜像,分别包括操作系统层、jdk等工具层、基础依赖jar包和配置文件层(这一层,需要用到使用dependency和resource插件,将那些通用的、基本不会变化的依赖包和资源文件独立打包置于这一层),备用。

        其次,每次发布最新代码,只需要将所有可执行代码独立成一个jar包,并加入到前面提到的三层基础docker镜像中,作为第四层存在(这一层的内容主要用到maven-jar-plugin插件),然后发布即可。这样既提高了docker镜像的复用,也减少了每次更新代码时所打的jar包的臃肿程度。

四:插件应用举例

        4.1:maven-jar-plugin 举例及部分说明

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.2.0</version>
    <configuration>
        <!-- 打包时包含的文件配置,在暗黑我的这个工程中,只打包 com 文件夹 -->
        <includes>
            <include>
                **/com/**
            </include>
        </includes>

        <archive>
            <manifest>
                <!-- 配置加入依赖包 -->
                <addClasspath>true</addClasspath>
                <classpathPrefix>lib/</classpathPrefix>
                <useUniqueVersions>false</useUniqueVersions>
                <!-- Spring Boot 启动类(自行修改) -->
                <mainClass>com.ccccit.springdockerserver.SpringDockerServerApplication</mainClass>
            </manifest>
            <manifestEntries>
                <!-- 外部资源路径加入 manifest.mf 的 Class-Path -->
                <Class-Path>resources/</Class-Path>
            </manifestEntries>
        </archive>
        <!-- jar 输出目录 -->
        <outputDirectory>${project.build.directory}/pack/</outputDirectory>
    </configuration>
</plugin>

       4.2:maven-dependency-plugin 举例及部分说明

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>3.2.0</version>
    <!-- 复制依赖 -->
    <executions>
        <execution>
            <!-- 这里的id可以随意写,与下面的goal无名称上的必然联系 -->
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
            <configuration>
                <!-- 依赖包 输出目录 -->
                <outputDirectory>${project.build.directory}/pack/lib</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

         对于maven-dependency-plugin插件而言,常用的"goal"包含以下几个内容,后续有时间也许会详细说明。

copy:拷贝指定jar包到指定目录,与当前工程的依赖没有关系

copy-dependencies:拷贝依赖jar包到指定目录

unpack:解压指定jar包到指定目录,与当前工程的依赖没有关系

unpack-dependencies:解压依赖jar包到指定目录

        4.3:maven-resources-plugin 举例及部分说明

<!-- 在打包时,动态将maven的参数传给resource文件夹下的参数 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>3.2.0</version>
    <configuration>
        <encoding>UTF-8</encoding>
        <!-- 当这里为true,那么resource文件夹下的配置文件,比如application.yml这些文件里面的${}包起来的内容就可以被pom文件中profiles标签下的对应名称部分行替换了 -->
        <useDefaultDelimiters>true</useDefaultDelimiters>
    </configuration>
    <!-- 复制资源和bin文件夹  -->
    <executions>
        <execution>
            <id>copy-resources</id>
            <phase>package</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <!-- 文件来源 -->
                        <directory>src/main/resources</directory>
                    </resource>
                </resources>
                <!-- 资源文件的输出目录 -->
                <outputDirectory>${project.build.directory}/pack/resources</outputDirectory>
            </configuration>
        </execution>
        <execution>
            <id>copy-bin</id>
            <phase>package</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <!-- 文件来源 -->
                        <directory>src/main/bin</directory>
                    </resource>
                </resources>
                <!-- 资源文件的输出目录 -->
                <outputDirectory>${project.build.directory}/pack/bin</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

        以下内容是对上面提到的profiles替换的举例。比如下面我自定义了名为 letmesee.reason的标签,那么如果上面的useDefaultDelimiters标签值为true,那么在打包或编译阶段,maven会将resource文件夹下的所有配置文件的对应内容做替换

<!-- pom 文件的 profiles部分 -->
<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <!-- 这里是让你自己随意定义属性用的,写成什么名字都无所谓,然后可以被resource中使用 -->
            <letmesee.reason>dev</letmesee.reason>
            <!-- 这里的 profiles.active 与其外层的profiles标签什么的毫无关系,仅仅是我碰巧起了个类似外层标签的名字,仅此而已 -->
            <profiles.active>dev</profiles.active>
        </properties>
        <!-- 是否为默认的环境 -->
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <profile>
        <id>shanxi</id>
        <properties>
            <letmesee.reason>shanxi</letmesee.reason>
            <profiles.active>shanxi</profiles.active>
        </properties>
    </profile>
</profiles>
## application.yml 文件中的部分内容
spring:
  profiles:
    #要注意的是,active这里可以使用的是maven配置中<properties> 标签下的任何一个标签,哪怕我自定义了一个letmesee的标签也无所谓
    active: ${letmesee.reason}

五:附录

Maven的内置参数

${basedir} 项目根目录
${project.build.directory} 构建终产物输出目录,缺省为target
${project.build.outputDirectory} 构建临时输出目录,缺省为target/classes
{project.build.finalName} 产出物名称,缺省为${project.artifactId}-${project.version}
${project.packaging} 打包类型,缺省为jar
${project.xxx} 当前pom文件的名为xxx节点内容