玩转 Spring Boot 应用篇(项目打包、发布)

2022-05-31 09:47:54 浏览数 (1)

0.

0.0. 历史文章整理

玩转 Spring Boot 入门篇

玩转 Spring Boot 集成篇(MySQL、Druid、HikariCP)

玩转 Spring Boot 集成篇(MyBatis、JPA、事务支持)

玩转 Spring Boot 集成篇(Redis)

玩转 Spring Boot 集成篇(Actuator、Spring Boot Admin)

玩转 Spring Boot 集成篇(RabbitMQ)

玩转 Spring Boot 集成篇(@Scheduled、静态、动态定时任务)

玩转 Spring Boot 集成篇(任务动态管理代码篇)

玩转 Spring Boot 集成篇(定时任务框架Quartz)

玩转 Spring Boot 原理篇(源码环境搭建)

玩转 Spring Boot 原理篇(核心注解知多少)

玩转 Spring Boot 原理篇(自动装配前凑之自定义Starter)

玩转 Spring Boot 原理篇(自动装配源码剖析)

玩转 Spring Boot 原理篇(启动机制源码剖析)

玩转 Spring Boot 原理篇(内嵌Tomcat实现原理&优雅停机源码剖析)

玩转 Spring Boot 应用篇(搭建菜菜的店铺)

玩转 Spring Boot 应用篇(解决菜菜店铺商品超卖问题)

玩转 Spring Boot 应用篇(引入Redis解决店铺高并发读的问题)

玩转 Spring Boot 应用篇(引入RabbitMQ解决店铺下单峰值问题)

玩转 Spring Boot 应用篇(序列号生成器服务实现)

0.1. 疑问

  • 开发出的 Spring Boot 应用,该如何打包?
  • 项目不可避免要引入三方依赖包,这种场景下该如何打包呢?
  • Spring Boot 应用编译打包后,该如何发布呢?

本次重点探讨 Spring Boot 应用的打包和发布。

1. 创建项目(ToyApp)

为了演示需要,基于 Spring Boot 创建一个 WEB 项目 ToyApp。

稍微注意一点:本次引入了一个三方依赖包(idgenerator-spring-boot-starter 是自定义的一个序列号生成器 starter)。

准备好环境,下面一起瞅瞅引入了三方依赖的 Spring Boot 该如何打包?

2. 编译打包

采用 IDEA 集成的 Maven 环境来对 Spring Boot 项目编译打包,可谓是超级 easy。

此时,通过反编译工具来瞅瞅编译打包成功之后的 ToyApp-0.0.1-SNAPSHOT.jar 里面的东西是否缺失,尤其是引入的三方依赖 jar 包。

通过反编译,发现引入的三方依赖 jar 包,没有打进去,咋回事儿?

由于 scope 为 system 的包 maven 默认是不打包进去的,所以解决方案就很简单:只需在 pom.xml 中指定一下 includeSystemScope 就可以。

代码语言:javascript复制
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <includeSystemScope>true</includeSystemScope>
            </configuration>
        </plugin>
    </plugins>
</build>

再次编译打包,然后对打成的 jar 包反编译观察一二。

至此,Spring Boot 项目打包就完成了,如果经历过传统的项目开发,相对传统的打包方式,你会知道着实简单不少。

3. 应用发布

3.1 一行命令的演化

运行 Spring Boot 打包之后的 jar 方式也简单,只需一行命令就行。

代码语言:javascript复制
java -jar /Users/caicai/ToyApp-0.0.1-SNAPSHOT.jar

执行效果:

此时,服务是启动了,但是不能关闭这个窗口,一旦关闭服务就停止了,不得不考虑后台运行,并且还想看日志,所以这一行命令演变成了这个鸟样。

代码语言:javascript复制
java -jar /Users/caicai/ToyApp-0.0.1-SNAPSHOT.jar > ToyApp.out &

执行启动时,效果如下,然后就可以轻松看日志输出了。

如果项目组中你既是研发又充当运维的角色,到这基本就完事儿了,因为相信通过熟练操作,会形成肌肉反应,你肯定能记住这一行命令。

不过,若是分工明确,生产权限隔离的话,一般都是运维同事来操作发布,所以还得想办法让运维同事省力,不得不考虑脚本化。

3.2 两个脚本

每个项目组的风格不同,而我习惯采取如下目录结构进行管理。

代码语言:javascript复制
.
├── bin(脚本存放目录)
│   ├── start.sh
│   └── stop.sh
├── lib(jar包存放目录)
│   └── ToyApp-0.0.1-SNAPSHOT.jar
└── logs(日志目录)
    ├── toyapp.gc.log
    └── toyapp.out

首先创建项目目录例如 toyapp,然后分别创建 bin、lib、logs 目录;把 ToyApp-0.0.1-SNAPSHOT.jar 拷贝至 lib 目录下;bin 目录主要存放脚本。

  • 启动脚本(start.sh)

在 bin 目录下,创建 start.sh,应用启动脚本。

代码语言:javascript复制
#!/bin/bash

#配置 Java 环境变量
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_251.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH
#定义应用名
App_Name=toyapp
#定义应用所在目录
App_Path=/Users/caicai/${App_Name}
#定义可执行文件的路径
JAR_PATH=${App_Path}/lib/ToyApp-0.0.1-SNAPSHOT.jar
#jvm启动参数
JAVA_OPTS="-Duser.timezone=GMT 8 -server -Xms4096m -Xmx4096m  -XX:MaxMetaspaceSize=256m -Xloggc:${App_Path}/logs/${App_Name}.gc.log -XX: UseConcMarkSweepGC -XX: UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=5 -XX: PrintGC -XX: PrintGCTimeStamps  -XX: PrintGCDetails  -XX: PrintGCApplicationStoppedTime"
#启动JAVA进程函数
CURRENT_COUNT=`ps -ef|grep java |grep ${App_Name} |grep -vc grep`
if [ $CURRENT_COUNT -eq 0 ]
then
        Log_Name=$(echo ${App_Name}|awk  -F"-" '{ print $NF }')
        nohup java -Dfunc_type=${App_Name}  $JAVA_OPTS  -Dfile.encoding=utf-8  -jar  $JAR_PATH  > ${App_Path}/logs/${Log_Name}.out  2>&1 &
  PROCESS_ID=`ps -ef | grep  "${App_Name}" |grep -v grep | awk '{ print $2 }'`
      echo "33[44;37m ☺☺☺☺☺启动应用 ${App_Name} 成功,进程 id 为 ${PROCESS_ID} ☺☺☺☺☺ 33[0m"
else
    echo "33[41;37m ☺☺☺☺☺ 应用 ${App_Name} 已经被启动了 ☺☺☺☺☺ 33[0m"
fi
  • 停止脚本(stop.sh)
代码语言:javascript复制
#!/bin/bash

# 定义应用名称
App_Name=toyapp

echo "33[44;37m ☺☺☺☺☺ 开始停止 ${App_Name} 应用 ☺☺☺☺☺ 33[0m"
ps -ef | grep ${App_Name} | grep -v grep | awk '{print$2}' | xargs kill
echo "33[41;37m ☺☺☺☺☺ 应用 ${App_Name} 停止成功!☺☺☺☺☺ 33[0m"
  • 脚本验证

应用启停脚本编写完成,执行脚本,蓝红搭配,sao 极了有没有?!

至此,Spring Boot 项目最基本的发布方式就完事了,可以直接执行脚本完成项目的启动和停止,爽歪歪!

4. 例行回顾

本文主要是对 Spring Boot 应用打包发布的探究,在面对引入三方依赖编译打包时,默认不会打进去,需要配置 includeSystemScope 方能包含 system 的三方依赖;接着重点讲解了如何用一行命令启动 Spring Boot 项目,以及如何把命令封装成脚本来对线上的应用进行发布操作。

如果你眼下运气欠佳,请不要气馁。一朵花的凋零荒芜不了整个春天,一次挫折也击垮不了整个人生。过去的已无法撤回,但未来还可努力书写。要相信,人生路上的每一次磨砺都是未来的铺垫 。 人民日报

0 人点赞