侧边栏壁纸
  • 累计撰写 18 篇文章
  • 累计创建 0 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

JPOM 实战(一):服务器部署 JPOM(JDK17 兼容版)

大锤灬
2026-01-22 / 0 评论 / 0 点赞 / 5 阅读 / 0 字

如果你和我一样:

  • 服务器是 Ubuntu

  • 面板用的是 宝塔

  • 项目想搞 CI / CD

  • 但每次看到 Jenkins 就有点 PTSD 😵‍💫

那么 JPOM 基本就是“运维友好型 CI 工具”的最优解之一。

本文将完整记录一次 从零开始 的实战过程:
服务器命令行部署 JPOM Server → 解决 JDK17 兼容问题 → 宝塔接管进程 → 配置域名 + SSL 访问,全程可复现、可抄作业。

适合人群

  • Java 后端 / 运维工程师

  • 正在使用宝塔,但 CI/CD 还没真正跑顺的人

  • 系统默认 JDK17,却被 JPOM 默认 JDK8 坑过的人(你懂的)

JPOM 官方地址:
👉 https://jpom.top/

一、服务器与基础环境说明

服务器环境

  • 系统:Ubuntu 20.04 / 22.04(实测均可)

  • 面板:宝塔 Linux 面板(正式版)

  • 运行服务:JPOM Server

JDK 环境规划(重点,敲黑板)

JDK

用途

JDK 17

运行你自己的 Java 项目

JDK 17

运行 JPOM(本文重点)

⚠️ 注意
JPOM 官方文档默认推荐 JDK8
如果你服务器 系统默认是 JDK17,但 JPOM 还用 JDK8 的启动方式跑,那后果基本就是:

能启动,但跑不稳
能访问,但日志全是反射警告
能用,但你会开始怀疑人生

所以:
一定要显式指定 JPOM 使用 JDK17 启动。

二、宝塔中安装 JDK17

路径如下:

宝塔 → 网站 → Java 项目 → Java 环境管理

选择并安装:JDK 17

安装完成后,宝塔通常会放在类似路径:/www/server/java/jdk-17.0.8/bin/java

⚠️ 实际路径以你服务器为准,可以通过宝塔终端确认。

三、安装 JPOM Server(命令行)

本文采用 官方推荐的默认安装方式,其他安装方式可自行查阅JPOM官网

1️⃣ 下载并安装 JPOM Server

在服务器中执行:curl -fsSL https://jpom.top/docs/install.sh | bash -s Server default

默认安装目录为:/usr/local/jpom-server/

2️⃣ 修改 JPOM 启动方式(JDK17 兼容核心)

进入目录:/usr/local/jpom-server/bin

创建并编辑 start.sh

#!/bin/bash
#
# JPOM Server auto-start script (JDK 17 compatible)
#

# ========================
# 强制使用宝塔 JDK 17
# ========================
JAVA_HOME="/www/server/java/jdk-17.0.8"
JAVA="${JAVA_HOME}/bin/java"

if [ ! -x "$JAVA" ]; then
  echo "ERROR: Java not found or not executable: $JAVA"
  exit 1
fi

# ========================
# 基础函数
# ========================
function absPath() {
  dir="$1"
  case "$(uname)" in
  Linux)
    readlink -f "$dir"
    ;;
  *)
    cd "$dir" || exit
    pwd
    ;;
  esac
}

function errorExit() {
  echo "$1" 2>&2
  exit 1
}

# ========================
# 目录定义
# ========================
bin_abs_path=$(absPath "$(dirname "$0")")
base=$(absPath "$bin_abs_path/../")

conf_path="${base}/conf"
Lib="${base}/lib/"
LogPath="${base}/logs/"
tmpdir="${base}/tmp/"
Log="${LogPath}/stdout.log"
logback_configurationFile="${conf_path}/logback.xml"
application_conf="${conf_path}/application.yml"
pidfile="$base/bin/server.pid"

PID_TAG="JPOM_SERVER_APPLICATION"
server_log="${LogPath}/server.log"

# ========================
# JVM 参数
# ========================
JAVA_OPTS="-Xss1024k \
-XX:-OmitStackTraceInFastThrow \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=${LogPath}"

# 内存参数
USR_JVM_SIZE="-Xms512m -Xmx512m"

JAVA_OPTS="-server ${USR_JVM_SIZE} \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=250 \
-XX:+ExplicitGCInvokesConcurrent \
${JAVA_OPTS}"

JAVA_OPTS="${JAVA_OPTS} \
-Djava.awt.headless=true \
-Djava.net.preferIPv4Stack=true \
-Dfile.encoding=UTF-8 \
-Dlogging.config=${logback_configurationFile} \
-Dspring.config.location=${application_conf} \
-Djava.io.tmpdir=${tmpdir}"

# ========================
# JDK17 模块开放(关键)
# ========================
JAVA_OPTS="${JAVA_OPTS} \
--add-opens=java.base/java.net=ALL-UNNAMED \
--add-opens=java.base/java.nio=ALL-UNNAMED \
--add-opens=java.base/java.lang=ALL-UNNAMED \
--add-opens=java.base/java.io=ALL-UNNAMED \
--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED"

MAIN_ARGS="$*"
mode="$2"
RUN_JAR=""

# ========================
# 校验配置
# ========================
function checkConfig() {
  mkdir -p "$LogPath" "$tmpdir"

  if [[ ! -f "$logback_configurationFile" ]] || [[ ! -f "$application_conf" ]]; then
    errorExit "Cannot find $application_conf or $logback_configurationFile"
  fi

  if [[ -z "${RUN_JAR}" ]]; then
    if [ -f "$Lib/run.bin" ]; then
      RUN_JAR=$(cat "$Lib/run.bin")
    else
      RUN_JAR=$(find "$Lib" -type f -name "*.jar" | sort | tail -1 | sed 's#.*/##')
    fi
  fi

  if [ ! -f "${Lib}${RUN_JAR}" ]; then
    errorExit "Jar not found: ${Lib}${RUN_JAR}"
  fi
}

# ========================
# PID 获取
# ========================
function getPid() {
  ps -ef | grep java | grep "$PID_TAG" | grep -v grep | awk '{print $2}'
}

# ========================
# 启动
# ========================
function start() {
  pid=$(getPid)
  if [ -n "$pid" ]; then
    echo "JPOM Server already running, pid=$pid"
    exit 0
  fi

  checkConfig

  command="${JAVA} -Djpom.application.tag=${PID_TAG} ${JAVA_OPTS} -jar ${Lib}${RUN_JAR} ${MAIN_ARGS}"
  echo "$command" > "$Log"

  nohup $command >> "$Log" 2>&1 &

  echo $! > "$pidfile"
  echo "JPOM Server started, pid=$!"
}

# ========================
# 停止
# ========================
function stop() {
  pid=$(getPid)
  if [ -n "$pid" ]; then
    echo "Stopping JPOM Server pid=$pid"
    kill "$pid"
    sleep 2
  else
    echo "JPOM Server not running"
  fi
  rm -f "$pidfile"
}

# ========================
# 状态
# ========================
function status() {
  pid=$(getPid)
  if [ -n "$pid" ]; then
    echo "JPOM Server running, pid=$pid"
  else
    echo "JPOM Server stopped"
  fi
}

# ========================
# 命令入口
# ========================
case "$1" in
start)
  start
  ;;
stop)
  stop
  ;;
restart)
  stop
  start
  ;;
status)
  status
  ;;
*)
  echo "Usage: $0 {start|stop|restart|status}"
  ;;
esac

3️⃣ 启动 JPOM

chmod +x start.sh
./start.sh start

查看运行日志:tail -500f /usr/local/jpom-server/logs/stdout.log

如果启动报错,90% 都能从日志里直接看出原因,别盯着宝塔页面发呆。

四、宝塔接管 JPOM 进程(关键一步)

JPOM 启动后,我们要让 宝塔来接管这个 Java 进程,否则:

  • 无法优雅重启

  • 无法绑定域名

  • SSL 配置会非常难受

1️⃣ 接管 JPOM 线程

路径:

宝塔 → 网站 → Java 项目 → 添加项目 → 接管原项目

选择:

  • 已启动的 JPOM Java 进程

2️⃣ 添加访问域名

在接管后的 Java 项目中:

设置 → 域名管理 → 添加域名

示例:jpom.template.com

五、Nginx 反向代理配置(JPOM 必须支持 WebSocket)

在该站点的 配置文件 中,加入以下核心配置:

server
{

   // 省略其他配置
    ……
    ……

    // 这里是核心配置
    #PROXY-LOCAl-START 代理本地服务的相关配置
    #PROXY-START/
    location / {
        proxy_pass http://127.0.0.1:2122;
        proxy_http_version 1.1;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # WebSocket(JPOM 必须)
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
    }
    #PROXY-END/
    ……
    ……
}

⚠️ JPOM 大量使用 WebSocket,如果少了这段,页面能打开,但功能会“间歇性失明”。

六、配置 SSL(Let’s Encrypt)

路径:

SSL → Let’s Encrypt

操作流程:

  1. 确认域名已正确解析到服务器 IP

  2. 申请证书

  3. 勾选 强制 HTTPS

宝塔会自动完成证书部署。

七、访问系统 & 初始化

现在,直接访问:https://jpom.template.com

根据页面提示创建 系统管理员账号,至此:

🎉 JPOM Server 已正式可用

总结一下(给未来的自己)

  • JPOM 很好用,但 JDK 版本一定要提前规划

  • 宝塔 + JPOM = 对运维非常友好的组合

  • JDK17 跑 JPOM 不是问题

    • 前提是:启动脚本你得自己接管

  • WebSocket + 反向代理 + SSL,一个都不能少

如果你现在:

  • 想把构建流程从「手动登录服务器」升级到「可视化 + 自动化」

  • 又不想被 Jenkins 的配置劝退

那 JPOM,真的值得一试。

0

评论区