# Jenkins教程 - 3 部署SpringBoot项目
下面使用 Jenkins + Git + Maven, 自动化部署一个 SpringBoot 项目。
# 3.1 准备SpringBoot项目
# 1 新建一个SpringBoot 项目
新建一个 SpringBoot 项目,这里我就在 SpringBoot 中新建一个 Controller。
只提供了一个接口,证明 SpringBoot 能访问运行就好了。
package com.doubibiji.hellospringboot.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String sayHello() {
return "Hello SpringBoot";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
项目结构:
# 2 将SpringBoot项目托管码云
Jenkins 服务后面需要从 git 仓库拉取代码进行构建,这里使用 gitee 码云来托管代码,所以这里将 SpringBoot 项目托管到码云。
这里细节就不介绍了,git 不太会的,可以学习本站的 git教程 (opens new window) 。
# 3.2 配置插件和工具
# 1 安装Maven插件
我们现在构建项目需要使用 Maven,所以还需要安装一个 Maven 插件。
在可用的插件中,搜索 maven,在搜索结果中选中 Maven Integration
进行安装。
拉到最下面,查看安装进度
# 2 配置Maven工具
我们的自动化构建任务是使用 Maven 构建的,需要告诉 Jenkins Maven的安装位置。
配置 Maven 的路径:
使用 mvn -v
可以查看 maven 安装的路径。
在前面已经配置了 Maven 使用阿里云的镜像。
# 3 安装SSH插件
这个插件的作用就是将 Jenkins 构建的 SpringBoot 项目的 jar 包发布的业务服务器上。
还是刚才安装插件的步骤:
# 4 配置业务服务器
后面需要将构建的 SpringBoot 的 jar 包发布到业务服务器,所以在这里配置一下要发布到的业务服务器的信息。
我也不知道选项为啥突然变成中文了,就是之前的 Manage Jenkins
下的 System
。
拉到最下面找到 Publish over SSH
,安装完 SSH 插件才有这个选项。
新增一个 SSH Server。
配置上面几个选项就可以了,配置完成,在最下面有个测试的按钮,可以测试一下配置有没有问题,没有问题,保存配置。
# 3.3 创建构建任务
# 1 新建任务
在 Jenkins 管理页面,新建Item,也就是新建构建任务。
填写任务名称:
选择Maven项目,前面安装Maven插件,才有这个选项!
# 2 源码管理
分支配置:
# 3 构建配置
上面使用默认配置即可。
- Pre Steps :表示构建前的工作,例如要执行一些脚本,这里我们不需要;
- Post Steps :表示构建后的工作;
- Root POM :指定构建使用的 pom.xml,这里表示在远程仓库的根目录下,如果远程仓库中,pom.xml不在根目录下,例如在 demo 目录下,则这里需要配置
demo/pom.xml
。
# 3.4 执行构建
前面的配置保存后,可以在控制台查看到配置的任务。如果要修改配置,直接点击任务 --> 配置,重新进行修改即可。
现在任务已经创建了,可以在任务列表,点击任务后面的按钮,手动执行构建。
执行后,在构建执行状态列表,可以看到构建的进度。
可以点击进去查看构建的控制台信息:
如果已经构建完成,也可以点击任务进入任务信息页面,查看构建失败的原因:
摸索一下页面的功能就好了。
第一次构建需要的时间可能比较久,因为要下载很多项目依赖的 jar 包。
构建如果成功,会显示成功,并在 jenkins
的工作空间下构建出 SpringBoot 项目的 jar 包。
如果没有成功,可以看一下日志,失败的原因是什么。
# 3.5 部署到业务服务器
上面的步骤只是在 Jenkins 服务器上生成了 jar 包,还没有一条龙执行到自动部署到业务服务器。下面继续。
# 1 配置传输
重新进入到构建任务的配置页面,对 Post Steps
进行配置,也就是构建后的操作。
选择 Send files or execute commands over SSH
。
因为 Jenkins 服务和 业务服务不是在同一个服务器上,所以才使用 Send files or execute commands over SSH
,如果在一台服务器 上,直接选择 执行 shell
就可以了,都不用将文件推送到别的服务器,直接使用shell命令 mv
去移动文件就可以了。
因为是不同服务器,所以需要使用SSH将文件传输到服务器,这里配置远程服务器信息,填写如下配置:
SSH Server:需要配置业务服务器,这里才有选择,看一下 3.2.4。
Source files :在 Jenkins 服务器上,构建的 jar 包在 Jenkins 的工作空间下,也就
~/.jenkins/workspace
,我这里构建的任务名称叫hello-jenkins
,所以 jar 包的地址是/home/doubi/.jenkins/workspace/hello-jenkins/target/hello-springboot-0.0.1-SNAPSHOT.jar
。这里填写的地址是从构建的任务所在的文件夹开始算的,也就是/home/doubi/.jenkins/workspace/hello-jenkins
算起,所以这里我填写了target/*.jar
,使用了通配符,表示target
目录下所有的 jar 包。Remote directory :表示传输到的远程服务器的路径,也是从家目录
~
开始算起,表示传输到~/projects
目录下,也就是传输到/home/doubi/projects
目录下,则传输完成,在业务服务器上 jar 包的路径是/home/doubi/projects/hello-springboot-0.0.1-SNAPSHOT.jar
,如果路径不存在,会自动创建。Remove prefix :这个表示删除的路径的前缀,如果不填写,则复制到远程后,会将
target
目录一起复制,会变成/home/doubi/projects/target/hello-springboot-0.0.1-SNAPSHOT.jar
,这里将target
路径删掉。Exec command :表示上传完成执行的命令,这里直接运行 jar 包,注意要使用 nohup 命令,在后台运行,并指定日志的输出,否则可能以为执行超时而失败。
执行的命令:
nohup java -jar /home/doubi/projects/hello-springboot-0.0.1-SNAPSHOT.jar > hello-springboot.log 2>&1 &
命令就是在后端运行jar包。
# 2 重新构建
除了可以点击 Dashboard 页面,任务列表后面的构建按钮,可以构建。
还可以在任务详情页面,点击 立即构建
按钮。
在 Jekins 的控制台页面,可以查看构建日志:
可以看到是否构建和传输成功,根据提示信息修改即可,如果传输成功,运行不成功,可以查看业务服务器上 jar 包有没有传输到对应的目录。
在 Post Steps
的 Send files or execute commands over SSH
的高级中,有一个 Exec timeout
选项,表示执行超时时间,默认是2分钟,如果任务构建时间比较长,可以将时间设置的长一些。
我这里是 201ms 就成功的。
# 3 访问SpringBoot项目
访问 SpringBoot 项目测试的接口,发现可以访问。
注意,上面传输完成的脚本只是启动了jar包,没有涉及到其他的操作,所以如果重新再执行构建,并不会将之前的 SpringBoot 项目停掉,而是会再次运行 SpringBoot 项目,会出现端口冲突,启动失败。
下面来处理这个问题。
# 4 执行脚本
在上面构建的时候,最终执行的命令是 nohup java -jar /home/doubi/projects/hello-springboot-0.0.1-SNAPSHOT.jar > hello-springboot.log 2>&1 &
,这个只是启动项目,没有备份、停止操作。
我们可以在业务服务器中,新建一个脚本文件,在脚本文件中进行备份、停止、启动项目的操作,然后在构架的时候,在 Post Steps
中执行这个脚本文件即可。
下面就是编写这个脚本文件,我这里起名叫 deploy.sh
#!/bin/bash
# jar包的名字
fileName=hello-springboot-0.0.1-SNAPSHOT.jar
# 这里是获取正在运行的程序的PID,通过PID来杀掉之前运行的程序
PID=$(ps -ef | grep $fileName | grep -v grep | awk '{ print $2 }')
# 如果PID不为空
if [ -n "${PID}" ];
then
# 杀掉程序
kill -9 $PID
echo 'Application is stopping...'
else
echo 'Application is not running'
fi
# 创建日志目录
mkdir -p "./logs/"
# 运行jar包
nohup java -jar ./$fileName > ./logs/hello-springboot.log 2>&1 &
# 创建备份目录(如果不存在)
mkdir -p "./packages/"
# 备份jar包
backupTimestamp=$(date +%Y%m%d%H%M)
cp $fileName ./packages/$backupTimestamp-$fileName
echo "backup jar success!"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
在上面的脚本中,进行了杀掉原来的程序、运行新的jar包,备份jar包的操作,编写完脚本文件,最好先本地执行测试一下,确保可用。
上面的 PID=$(ps -ef | grep $fileName | grep -v grep | awk '{ print $2 }')
就是从下面查询到的进程信息中获取正在运行的项目的PID 赋值给 PID 变量。
grep $fileName
就是过滤名称带有 hello-springboot-0.0.1-SNAPSHOT.jar
的进程,如下图:
grep -v grep
就是再过滤掉含有 grep
的进程,那么就剩下第一条记录,awk '{ print $2 }'
表示取出这个记录中的第二个字段,也就是PID 2483
。
然后给这个文件添加执行权限:
chmod +x deploy.sh
脚本写好了,现在让 Jenkins 直接在上传完文件执行这个脚本就可以了。
重新配置 Post Steps
:
配置完成,重新直接构建,可以看到,每次SpringBoot项目都会重启启动执行。
# 5 修改SpringBoot项目
现在重新修改SpringBoot项目,上传到gitee码云,然后使用 Jenkins 重新执行构建,看看能否自动拉取代码,完成自动部署更新。
重新修改 SpringBoot Controller的代码:
@RestController
public class HelloController {
@GetMapping("/hello")
public String sayHello() {
return "Hello www.doubibiji.com";
}
}
2
3
4
5
6
7
8
9
并推送到 gitee。
然后重新使用 Jekins 执行构建。构建完成,访问 SpringBoot 项目。发现自动构建更新完成。
至此,完成了整个 SpringBoot 项目的自动构建。
← 02-环境安装 04-监听Git代码变化 →