📌 前言
在企业级开发中,我们常常面临 新老项目并存 的复杂局面:
老项目基于 JDK 8 开发,短期内无法升级;
新项目采用 JDK 17(LTS)甚至更高版本;
而作为 CI/CD 核心的 Jenkins,官方推荐使用 JDK 11+,最新版本更建议使用 JDK 17 或 JDK 21 以获得最佳性能和安全性。
如何在一个环境中统一管理多个 JDK 版本,让 Jenkins 自身运行在现代 JDK 上,同时又能灵活构建不同 JDK 版本的项目?
本文将带你从零开始,完成:
✅ 安装 JDK8、JDK17、JDK21
✅ 使用 JDK21 部署 Jenkins(WAR 方式)
✅ 配置 Jenkins 支持多版本 JDK 构建任务
✅ 实际验证不同 JDK 项目的自动化构建
1. 安装JDK
(1) 下载JDK并且解压到指定路径,如图是解压后的路径
(2)修改/etc/profile,添加以下内容
JAVA_HOME=/usr/local/java/jdk1.8.0_212
JRE_HOME=/usr/local/java/jdk1.8.0_212/jre
CLASS_PATH=:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
alias java8='export JAVA_HOME=/usr/local/java/jdk1.8.0_212 && export CLASSPATH=.:${JAVA_HOME}/lib && export PATH=${JAVA_HOME}/bin:$PATH && java -version'
alias java17='export JAVA_HOME=/usr/local/java/jdk17 && export CLASSPATH=.:${JAVA_HOME}/lib && export PATH=${JAVA_HOME}/bin:$PATH && java -version'
alias java21='export JAVA_HOME=/usr/local/java/jdk21 && export CLASSPATH=.:${JAVA_HOME}/lib && export PATH=${JAVA_HOME}/bin:$PATH && java -version'
然后执行 source /etc/profile
然后输入java8,java17,java21,可以切换到指定版本的jdk
2. 安装jenkins
(1)下载jenkins war包
https://www.jenkins.io/doc/book/installing/war-file/
(2)上传war包,并且启动
在启动jenkins之前,需要安装字体,否则启动失败
## 安装字体
sudo yum install -y fontconfig
sudo yum install -y liberation-fonts
## 切换到jdk21
java21
## 指定自定义端口8888
nohup java -jar jenkins.war --logfile=/opt/jenkins/jenkins.log --httpPort=8888 &
(3) 设置账号,以下均为截图
浏览器输入ip:8888 ,获取管理员密码,然后进入开始设置
点击开始使用jenkins,到此已经算安装成功
(4)安装插件
安装插件(我们需要实现拉取代码,打包,部署(单节点,跨节点))
Localization: Chinese (Simplified)
Maven Integration
Publish Over SSH
SSH Build Agents
SSH Agent
Pipeline
Git client
Git
安装完成后重启,可以在浏览器输入:ip:8888/restart
(5) jenkins 机器安装插件
(a)安装maven
修改/etc/profile
export MAVEN_HOME=/usr/local/maven
export PATH=${MAVEN_HOME}/bin:${PATH}
source /etc/profile
(b)安装git
yum install git
说明:在这块安装了maven和git就是让服务器去操作打包和拉取代码的事情,不让jenkins去操作打包(可能有矛盾,jenkins让打包,其实打包还是在服务器上)
(6)凭据管理
在这块输入服务器的账密和git的私钥
这里面的ID就是唯一值,后面在节点管理或者Pipeline代码块用
(7)节点管理
(8) 创建作业
bash
pipeline {
agent none
environment {
// Git 仓库
GIT_REPO = 'ssh://git@ip:10022/admin/xgov-agent.git'
// 本地构建路径(在 Jenkins Master 上)
WORKSPACE = "${APP_DIR}/workspace"
BUILD_JAR_DIR = "${WORKSPACE}/jars"
DEPLOY_DIR = "${APP_DIR}/app"
TARGET_ZIP = "${APP_NAME}.zip"
// yeexun170 部署配置
NODE_DEPLOY_USER = 'root' // yeexun170 上的用户名
NODE_DEPLOY_HOST = '172.32.1.170' // 主机名或 IP
NODE_DEPLOY_DIR = "/opt/apps/${APP_NAME}" // yeexun170 上的部署目录
// Java 启动参数
JAVA_OPTS = '-Xms512m -Xmx1024m'
START_JAR = "${APP_NAME}.jar"
}
stages {
stage('准备目录') {
agent {label 'master'}
steps {
script {
echo "📁 准备本地构建目录"
}
sh """
rm -rf ${WORKSPACE}/* .git
mkdir -p ${WORKSPACE}
echo "✅ 目录已清理"
"""
}
}
stage('拉取代码') {
agent {label 'master'}
steps {
script {
echo "🔧 拉取代码:${GIT_REPO} 分支:${BRANCH}"
}
checkout changelog: false, scm: [
$class: 'GitSCM',
branches: [[name: '${BRANCH}']],
doGenerateSubmoduleConfigurations: false,
extensions: [
[$class: 'CloneOption', depth: 1, noTags: false, reference: '', shallow: true, timeout: 30]
],
submoduleCfg: [],
userRemoteConfigs: [
[credentialsId: '001', url: 'ssh://git@172.32.1.6:10022/admin/xgov-agent.git']
]
]
}
}
stage('Maven 打包') {
agent {label 'master'}
steps {
script {
echo "📦 使用 Maven 打包(Java 17)..."
}
sh """
# jenkins 把代码拉取到这个位置
cd /root/.jenkins/workspace/test_node
# 加载环境
source /etc/profile || true
# 切换 Java 17(根据实际路径调整)
java17
java -version
if [ ! -f pom.xml ]; then
echo "❌ 未找到 pom.xml"
exit 1
fi
mvn clean install -DskipTests
if [ \$? -ne 0 ]; then
echo "❌ Maven 构建失败"
exit 1
fi
"""
}
}
stage('创建传输路径') {
agent {label 'yeexun170'}
steps {
script {
echo "🚚 创建路径"
}
sh """
mkdir -p ${NODE_DEPLOY_DIR}
echo "路径创建成功"
"""
}
}
stage('SCP 上传到 yeexun170') {
agent {label 'master'}
steps {
script {
echo "🚚 正在上传到 /root/.jenkins/workspace/test_node/jars:${NODE_DEPLOY_DIR}"
}
sh """
scp /root/.jenkins/workspace/test_node/jars/${TARGET_ZIP} ${NODE_DEPLOY_USER}@${NODE_DEPLOY_HOST}:${NODE_DEPLOY_DIR}/
if [ \$? -eq 0 ]; then
echo "✅ 文件已上传到 yeexun170"
else
echo "❌ SCP 上传失败,请检查 SSH 连接"
exit 1
fi
"""
}
}
stage('在 yeexun170 上部署并启动') {
agent {label 'yeexun170'}
steps {
script {
echo "🚀 在 yeexun170 上部署并启动服务"
}
sh """
# 加载环境
source /etc/profile || true
# 切换 Java 17(根据实际路径调整)
java17
java -version
echo "📦 准备新版本文件..."
cd ${NODE_DEPLOY_DIR}
# 1. 备份旧版本(如果存在)
if [ -d ${APP_NAME} ]; then
echo '📁 备份旧版本'
rm -rf ${APP_NAME}_old
mv ${APP_NAME} ${APP_NAME}_old
fi
# 2. 解压新版本到临时目录
if [ ! -f ${TARGET_ZIP} ]; then
echo '❌ 错误:未找到更新包 ${TARGET_ZIP}'
exit 1
fi
echo '📦 解压新版本...'
unzip ${TARGET_ZIP}
if [ \$? -ne 0 ]; then
echo '❌ 解压失败,恢复旧版本'
[ -d ${APP_NAME}_old ] && mv ${APP_NAME}_old ${APP_NAME}
exit 1
fi
# 4. 停止旧服务(最后才停)
PID=\$(ps aux | grep '${START_JAR}' | grep -v 'grep' | awk '{print \$2}')
if [ -n \"\$PID\" ]; then
echo \"🛑 停止旧服务 PID: \$PID\"
kill -15 \$PID
sleep 8
if ps -p \$PID > /dev/null 2>&1; then
kill -9 \$PID
echo \"✅ 强制终止\"
fi
fi
# 5. 启动新服务
echo '🚀 启动新服务...'
cd ${NODE_DEPLOY_DIR }/${APP_NAME}
JENKINS_NODE_COOKIE=dontKillMe nohup java \${JAVA_OPTS} -jar ${START_JAR} > app.log 2>&1 &
# 6. 检查是否启动成功
sleep 10
if pgrep -f \"java.*${APP_NAME}\" > /dev/null; then
echo '✅ 服务已启动'
else
echo '❌ 启动失败,请检查日志'
tail -n 30 app.log
exit 1
fi
"""
}
}
}
}