Spring Boot 项目打包静态资源分离实践
Spring Boot 打包远程执行代码admin 发布于:2023-02-19 10:16:16
阅读:loading
前面一篇《Spring Boot 项目assembly打包实践》介绍了非常高端的企业级打包实战,自以为是非常完美的,然而最终还是被水平限制了,其中重要的一点是没有将静态资源给剥离出来,当时属实不知道剥离出来后可以起到热更新的作用,所以也就没有认识到有非常高的必要性,直到前天在友链站点看到了《spring boot项目使用maven插件将项目和jar包依赖以及静态资源分离打包》这篇文章(实际之前也看到过几次),专门留言问了一下是否能够支持资源文件的热更新,得到博主的肯定回复,不禁又来了兴趣,所以就有了关于项目打包的本篇文章和后续一篇。
实际在前三四年前最初体验到Spring Boot项目工程的部署运行时,当时的所有资源文件均在于一个jar(并不是仅一个jar包),当时提出了一个意见就是前台的项目打个war包要比这种jar包要合理啊,毕竟war包中的前端资源文件更改了可以立即生效,得到不认可的态度,也认为war是过失淘汰的产物,不过我还是认为存在就有它的合理性,选择合理的时机应用即可,毕竟这几年以来前台项目稍微变更一丢丢都需要走部署上线的流程。
本次实践重点在于改造博客示例项目的代码,调整打包实现,将静态资源(image,css,js等)和thymeleaf的template模板资源从jar包中拆离出去,前者是直接使用浏览器访问的,后者是需要访问controller地址后进行的页面跳转,来验证这些文件是否能够热更新,实际还有一些类似Excel导出模板和Freemarker的模板是否支持热更新,未作验证,详细过程参考下文。
<build>
<plugins>
<!-- 打JAR包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<!-- 不打包资源文件(配置文件和依赖包分开) -->
<excludes>
<exclude>*.yaml</exclude>
<exclude>*.xml</exclude>
<exclude>prod/**</exclude>
<exclude>test/**</exclude>
<exclude>config/**</exclude>
</excludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!-- MANIFEST.MF 中 Class-Path 加入前缀 -->
<classpathPrefix>lib</classpathPrefix>
<!-- jar包不包含唯一版本标识 -->
<useUniqueVersions>false</useUniqueVersions>
<!--指定入口类 -->
<mainClass>cn.chendd.Bootstrap</mainClass>
</manifest>
<manifestEntries>
<!--MANIFEST.MF 中 Class-Path 加入资源文件目录 -->
<Class-Path>conf/</Class-Path>
</manifestEntries>
</archive>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</plugin>
<!-- 该插件的作用是用于复制依赖的jar包到指定的文件夹里 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- 该插件的作用是用于复制指定的文件 -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution> <!-- 复制配置文件 -->
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>*/**</include>
</includes>
<excludes>
<exclude>prod/**</exclude>
<exclude>test/**</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/views</directory>
<includes>
<include>*/**</include>
</includes>
</resource>
</resources>
<outputDirectory>${project.build.directory}/conf</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
【脚本说明】
(1)manifest节点中定义了mainClass主启动类,以当前模块admin打包为admin.jar为主核心jar文件,classpathPrefix标签定义了主jar所依赖的其它目录的文件夹结构层级,如果该标签配置空白字符,则表示admin.jar要与其它依赖的jar隶属于同级目录;
(2)Class-Path目录定义了资源配置文件与主admin.jar的目录层级,若属于同级目录则可为“conf/”,所为上级目录可为“../conf/”,必须以/结尾;
(3)如果定义了这两个目录,打包时将严格按照这些配置生效,它们决定了最终的启动命令,如可以使用java -jar admin-1.0-SNAPSHOT.jar直接运行,可以不用指定“-Dloader.path=conf,lib”;具体的打包命令和打包时的上述两个参数有严格的依赖关系,目录结构要严格匹配,假如启动命令是以打包目录中的bin目录执行的,则打包命令参考为:“java -jar ../lib/admin-1.0-SNAPSHOT.jar”,此时说明,主jar包admin.jar与其它依赖jar均属于lib目录下,且lib目录与conf目录同级别,所以上述的两个参数中classpathPrefix的值应该是“空”,Class-Path的值应该是“../conf/”;
(4)打包命令参考为:“clean compile package -Dmaven.test.skip=true -f pom.xml”,也可以在IDEA中右侧maven面板中,进行打包;
【打包说明】
(1)除了框起来的conf和lib及admin-1.0-SNAPSHOT.jar以外的其它文件夹均可删除;
(2)精简后的目录在运行后输出logs文件夹,该文件夹为日志的输出路径,参考如下:
【运行说明】
(1)conf目录为静态资源目录和配置文件目录,其中statics为静态资源目录,templates为thymeleaf模板路径,其它路径为classes中的配置文件;
(2)修改statics路径下的readme.txt文件,验证更新生效;
(3)在statics路径下增加lhk.jpg文件,验证增加文件生效;
(4)在templates目录下的usage目录的simple.html更新,验证修改模板文件生效(该文件内部有包含thymeleaf标签);
(5)本例验证项目源码可见:源码下载.zip;
(6)本例的实践定位是小试项目打包资源的分离,后文将会有更加专业和更具维护的企业级应用打包实践;
点赞