Spring Boot 项目assembly打包实践

Spring Boot 打包远程执行代码
placeholder image
admin 发布于:2022-05-09 10:29:43
阅读:loading

1.打包插件依赖

曾经花费好多时间的各种折腾关于打包的实践,主要侧重于三种实现:spring-boot-maven-plugin、appassembler-maven-plugin和maven-assembly-plugin,最终由于几个原因选择了assembly进行实践,在打包本站博客系统时也遇到了一些问题,最终也是友好的解决,在打包时也使用到了maven的其它插件,参考如下:

(1)maven-resources-plugin:在打包或build资源文件时,项目的各种文件会被重新复制生成,某些文件在重新生成的过程中会被改写,追加一些其它的东西后重新生成新文件,如此就导致原有文件的MD5发生了变化,如本站打包时https的证书文件后缀名为“pfx”(证数文件名称为www.chendd.cn.pfx)就被追加生成新文件,所以解决该类问题特增加该插件,排除一些需要过滤的文件,此处的排除并不是不拷贝生成文件,而是排除该类文件被覆盖追加生成新文件,即保持原有文件的拷贝输出,防止造成文件的不可用;

(2)maven-jar-plugin:该插件会将各个module打包为jar文件,同时也可以指定jar文件中的Main-Class启动类,同时可以将resources目录中的某些资源文件或文件夹给排除掉,使得jar包中的文件更加纯粹,可以只包含class和templates以及statics等文件,注意由于该插件在某个module被引用的,排除的文件或文件夹仅只会适用于排除该module下的文件(夹);

(3)copy-rename-maven-plugin和maven-antrun-plugin:拷贝文件并重命名插件,在实践分环境打包时准备用于按分环境的文件夹生成对应的文件,其中有个插件的源代码实现必须限定要重命名的文件必须存在,如果文件不存在不重命名即可,但是抛出错误异常了,导致最终该插件并未使用

(4)maven-assembly-plugin:Apache打包插件,在打包时同时会先运行(1)(2)的插件,同时运行该插件,该插件使用定制的打包脚本assembly.xml进行深度定制;

2.打包需求

(1)打包将resources目录下的配置文件单独存放于conf文件夹,在jar包中不包含配置文件;

(2)打包支持生成新的空白文件夹(配合启动脚本使用,常见的有:logs、runtime、temp等),支持拷贝文件夹和文件至指定位置;

(3)打包若干个jar文件拆成多个文件夹存放,将第三方jar存放于lib-jar、将本地jar(使用systemPath引入的本地路径jar)存放于lib-local、将项目中的各个module的jar存放于lib-project;

(4)打包支持多环境场景,支持不通环境打包,打包时传递不通的环境标识生成对应环境的配置文件;

打包目录.gif

3.assembly插件知识点

(1)<finalName>chendd</finalName>标签定义生成打包文件的文件夹前缀名称(见pom.xml文件中引用插件时);

(2)<id>admin</id>标签生成的根文件夹名称为:pom.xml中finalName定义的前缀 + '-' + 此处的id,即打包生成根文件夹为“chendd-admin”;

(3)<format>dir</format>标签指定打包文件夹最终的生成格式,可以是:zip、tar、tar.gz、jar、dir、war等;

(4)<includeBaseDirectory>false</includeBaseDirectory>是否在target目录下创建一个根文件夹,取名<baseDirectory>中的文本;

(5)<baseDirectory>admin-all</baseDirectory>当<includeBaseDirectory>标签为true时有效,会在chendd-admin目录中再生成一个根文件夹,取名为此处定义的admin-all;

(6)<fileSets>指定要包含在程序集中的文件组,指定源文件对应的输出位置和文件权限以及换行符等,支持pom.xml中定义的变量引用,同时可以排除某些文件夹,实现按环境打包的重要标签之一;

(7)<files>创建文件夹以及重命名资源文件,重命名资源文件名称,但当文件不存在时报错了,使用copy-rename-maven-plugin插件解决,同时可以生成空白文件夹;

(8)<dependencySets>处理项目依赖的jar配置,可按jar包路径和依赖jar文件的范围(runtime/test/system等)来筛选文件,实现不同的文件存储到不同的目录中;

4.项目目录结构

image.png

打包说明

(1)项目名称为chendd-blog-examples,执行打包时需要执行上图中的“项目pom.xml”,执行时可以同时支持多个module的打包逻辑(本站博客系统2.0会同时打包admin和web相关module,本例只打包admin模块);

(2)在admin模块的/src/main/resources目录下,配置文件为application.yaml和config目录,test目录与prod目录为区分环境打包的目录,此两个目录中包含了全量的配置文件,打包时若不指定环境则默认取/src/main/resources目录中的application.yaml和config目录作为开发环境的打包结果,忽略掉test和prod目录;若打包test环境时将只获取test目录下的所有文件,同时将application-test.yaml文件重命名为application.yaml;若打包prod环境时同样只获取prod目录中的所有文件,将application-prod.yaml重命名为application.yaml;

(3)IDEA有个问题当一个项目模块中若存在多个同名application.yaml时,会导致编写application.yaml内容时无参数代码提示,故本站为了解决此问题,特将不同环境下的此文件均增加了环境标识

(4)打包命令使用了clean compile package 先清理再编译后打包的步骤,同时区分环境打包使用-P参数,跳过测试的运行使用-Dmaven.test.skip,参考如下:

默认打包开发环境:clean compile package -Dmaven.test.skip=true -f pom.xml

打包test环境:clean compile package -Ptest -Dmaven.test.skip=true -f pom.xml

打包prod环境:clean compile package -Pprod -Dmaven.test.skip=true -f pom.xml

(5)打包需求处的描述均已满足,若本文给出的示例打包时找不到gif包记得关闭maven的offline模式,仅从本地maven仓库中寻找jar;

5.参考代码

admin模块pom.xml

<!-- 使用maven-assembly-plugin插件打包 -->
<build>
    <finalName>${project.artifactId}-${project.version}</finalName>
    <sourceDirectory>src/main/java</sourceDirectory>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <!--该模块中的resources中的配置文件是否需要打包入jar文件中-->
            <includes>
                <include>**/*.*</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.*</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/views</directory>
            <includes>
                <include>**/*.*</include>
            </includes>
        </resource>
    </resources>

    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <configuration>
                <!-- 排除一些过滤的文件,由于编译会更改相关文件内容,导致文件不可用,如www.chendd.cn.pfx -->
                <nonFilteredFileExtensions>
                    <nonFilteredFileExtension>pfx</nonFilteredFileExtension>
                </nonFilteredFileExtensions>
            </configuration>
        </plugin>
        <!-- 设置程序启动的Main Class -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.2.2</version>
            <!--打包时排除jar中的资源文件-->
            <executions>
                <execution>
                    <phase>package</phase>
                </execution>
            </executions>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix></classpathPrefix>
                        <mainClass>cn.chendd.Bootstrap</mainClass>
                    </manifest>
                </archive>
                <excludes>
                    <exclude>/application*.yaml</exclude>
                    <exclude>/config/**</exclude>
                    <exclude>/prod/**</exclude>
                    <exclude>/test/**</exclude>
                    <exclude>**/*.java</exclude>
                </excludes>
            </configuration>
        </plugin>
        <!-- 打包插件 -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.3.0</version>
            <executions>
                <!-- 配置执行器 -->
                <execution>
                    <id>assembly-admin</id>
                    <!-- 绑定到package生命周期阶段上 -->
                    <phase>package</phase>
                    <goals>
                        <!-- 只运行一次,会生拷贝响应的文件至输出目录 -->
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <!--打包文件夹目录名称,默认格式为artifactId-version-->
                <finalName>chendd</finalName>
                <descriptors>
                    <!--assembly配置文件路径-->
                    <descriptor>src/assembly/assembly.xml</descriptor>
                </descriptors>
            </configuration>
        </plugin>
    </plugins>
</build>

<!-- 打包环境参数 -->
<profiles>
    <profile>
        <id>dev</id>
        <!-- 默认打包采取的模式 -->
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
            <filters.envFolder>src/main/resources</filters.envFolder>
            <filters.envName></filters.envName>
        </properties>
    </profile>
    <profile>
        <id>test</id>
        <properties>
            <filters.envFolder>src/main/resources/test</filters.envFolder>
            <filters.envName>-test</filters.envName>
        </properties>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <filters.envFolder>src/main/resources/prod</filters.envFolder>
            <filters.envName>-prod</filters.envName>
        </properties>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
    </profile>
</profiles>

admin模块assembly.xml

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">

    <!--
        apache plugin项目地址:https://maven.apache.org/plugins/maven-assembly-plugin/assembly.html
        <id>此程序集的id<id>
        <format>常见的打包文件格式:zip、tar、tar.gz、jar、dir、war等</format>
        <includeBaseDirectory>在最终存档中包含一个基本目录</includeBaseDirectory>
    -->
    <!--生成的根文件夹名称为:pom.xml中finalName定义的前缀 + '-' + 此处的id-->
    <id>admin</id>
    <formats>
        <!--打包的文件格式,可以是:dir、war、zip、tar.gz-->
        <format>dir</format>
    </formats>
    <!--是否在target目录下创建一个根文件夹,取名baseDirectory-->
    <includeBaseDirectory>false</includeBaseDirectory>
    <baseDirectory>admin-all</baseDirectory>

    <!--指定要包含在程序集中的文件组-->
    <fileSets>
        <fileSet>
            <directory>src/bin</directory>
            <directoryMode>0755</directoryMode>
            <fileMode>0777</fileMode>
            <outputDirectory>bin</outputDirectory>
            <lineEnding>unix</lineEnding>
        </fileSet>
        <fileSet>
            <directory>${filters.envFolder}</directory>
            <excludes>
                <!--根据环境设置排除的目录,若打包为test环境时排除src/main/resources/test/test/**路径-->
                <exclude>test/**</exclude>
                <exclude>prod/**</exclude>
                <!--此文件由下方特殊处理-->
                <exclude>application${filters.envName}.yaml</exclude>
            </excludes>
            <outputDirectory>conf</outputDirectory>
        </fileSet>
    </fileSets>

    <!--创建文件夹以及重命名资源文件-->
    <files>
        <!-- 重命名资源文件名称,但当文件不存在时报错了,使用copy-rename-maven-plugin插件解决 -->
        <file>
            <source>${filters.envFolder}/application${filters.envName}.yaml</source>
            <outputDirectory>conf</outputDirectory>
            <destName>application.yaml</destName>
            <filtered>true</filtered>
        </file>
        <!--创建runtime文件夹用于启动命令时指定临时目录-Djava.io.tmpdir-->
        <file>
            <source></source>
            <outputDirectory>runtime</outputDirectory>
        </file>
        <!--创建logs文件夹用于输出日志文件时的根目录-->
        <file>
            <source></source>
            <outputDirectory>logs</outputDirectory>
        </file>
    </files>

    <!--项目依赖的jar配置-->
    <dependencySets>
        <dependencySet>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib-jar</outputDirectory>
            <!--是否解压缩jar文件-->
            <unpack>false</unpack>
            <!--依赖jar文件的范围-->
            <scope>runtime</scope>
            <!--排除项目内的jar-->
            <excludes>
                <exclude>cn.chendd*:*</exclude>
            </excludes>
        </dependencySet>
        <dependencySet>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib-local</outputDirectory>
            <unpack>false</unpack>
            <!--将使用SystemPath依赖的本地jar拷贝至同级目录-->
            <scope>system</scope>
            <!--排除项目内的jar-->
            <excludes>
                <exclude>cn.chendd*:*</exclude>
            </excludes>
        </dependencySet>
        <dependencySet>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib-project</outputDirectory>
            <unpack>false</unpack>
            <includes>
                <include>cn.chendd*:*</include>
            </includes>
        </dependencySet>
    </dependencySets>

</assembly>

6.源码下载

源码工程下载可转至https://gitee.com/88911006/chendd-blog-examples项目的PackageAssembly分支;

 点赞


 发表评论

当前回复:作者

 评论列表


留言区