云计算百科
云计算领域专业知识百科平台

宝塔部署SpringBoot3.2到HTTPS的坑清单

宝塔面板部署 Spring Boot 3.2:从 jar 到 HTTPS 的常见坑清单

把 Spring Boot 3.2 的 jar 部署到宝塔并配好 HTTPS,失败通常落在三个位置。jar 直接起不来,日志第一行写着 UnsupportedClassVersionError,class file version 61.0。jar 起来得很干净,浏览器一访问却在 https 和 http 之间来回跳,或者上传稍大的文件就报 413。前面都通了,证书到期的某一天整站突然打不开。

这三类失败各自堵着一个接口。第一类卡在 JDK 与字节码之间,第二类卡在 nginx 与应用的转发约定上,第三类卡在证书续期与 nginx 重载的衔接上。报错出现在哪一层,就先查哪一层。每条坑下面都给报错特征、原因、修法和一个本地自查命令,方便照着跑。

清单里的版本事实按 Spring Boot 3.2 这一代的公开文档口径,nginx 部分按官方模块的默认值,命令都可以在你的服务器上直接执行。宝塔面板各版本的界面和生成的配置有差别,写到面板的地方以你手里的版本为准。

下面是整份清单的排错总览。失败按启动层、反代层、证书层三层展开,报错出现在哪一层,就先查哪一层:

#mermaid-svg-PODTh9I8xVYHQ3ci{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PODTh9I8xVYHQ3ci .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PODTh9I8xVYHQ3ci .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PODTh9I8xVYHQ3ci .error-icon{fill:#552222;}#mermaid-svg-PODTh9I8xVYHQ3ci .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PODTh9I8xVYHQ3ci .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PODTh9I8xVYHQ3ci .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PODTh9I8xVYHQ3ci .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PODTh9I8xVYHQ3ci .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PODTh9I8xVYHQ3ci .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PODTh9I8xVYHQ3ci .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PODTh9I8xVYHQ3ci .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PODTh9I8xVYHQ3ci .marker.cross{stroke:#333333;}#mermaid-svg-PODTh9I8xVYHQ3ci svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PODTh9I8xVYHQ3ci p{margin:0;}#mermaid-svg-PODTh9I8xVYHQ3ci .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-PODTh9I8xVYHQ3ci .cluster-label text{fill:#333;}#mermaid-svg-PODTh9I8xVYHQ3ci .cluster-label span{color:#333;}#mermaid-svg-PODTh9I8xVYHQ3ci .cluster-label span p{background-color:transparent;}#mermaid-svg-PODTh9I8xVYHQ3ci .label text,#mermaid-svg-PODTh9I8xVYHQ3ci span{fill:#333;color:#333;}#mermaid-svg-PODTh9I8xVYHQ3ci .node rect,#mermaid-svg-PODTh9I8xVYHQ3ci .node circle,#mermaid-svg-PODTh9I8xVYHQ3ci .node ellipse,#mermaid-svg-PODTh9I8xVYHQ3ci .node polygon,#mermaid-svg-PODTh9I8xVYHQ3ci .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PODTh9I8xVYHQ3ci .rough-node .label text,#mermaid-svg-PODTh9I8xVYHQ3ci .node .label text,#mermaid-svg-PODTh9I8xVYHQ3ci .image-shape .label,#mermaid-svg-PODTh9I8xVYHQ3ci .icon-shape .label{text-anchor:middle;}#mermaid-svg-PODTh9I8xVYHQ3ci .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PODTh9I8xVYHQ3ci .rough-node .label,#mermaid-svg-PODTh9I8xVYHQ3ci .node .label,#mermaid-svg-PODTh9I8xVYHQ3ci .image-shape .label,#mermaid-svg-PODTh9I8xVYHQ3ci .icon-shape .label{text-align:center;}#mermaid-svg-PODTh9I8xVYHQ3ci .node.clickable{cursor:pointer;}#mermaid-svg-PODTh9I8xVYHQ3ci .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PODTh9I8xVYHQ3ci .arrowheadPath{fill:#333333;}#mermaid-svg-PODTh9I8xVYHQ3ci .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PODTh9I8xVYHQ3ci .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PODTh9I8xVYHQ3ci .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PODTh9I8xVYHQ3ci .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PODTh9I8xVYHQ3ci .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PODTh9I8xVYHQ3ci .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PODTh9I8xVYHQ3ci .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PODTh9I8xVYHQ3ci .cluster text{fill:#333;}#mermaid-svg-PODTh9I8xVYHQ3ci .cluster span{color:#333;}#mermaid-svg-PODTh9I8xVYHQ3ci div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PODTh9I8xVYHQ3ci .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PODTh9I8xVYHQ3ci rect.text{fill:none;stroke-width:0;}#mermaid-svg-PODTh9I8xVYHQ3ci .icon-shape,#mermaid-svg-PODTh9I8xVYHQ3ci .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PODTh9I8xVYHQ3ci .icon-shape p,#mermaid-svg-PODTh9I8xVYHQ3ci .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PODTh9I8xVYHQ3ci .icon-shape .label rect,#mermaid-svg-PODTh9I8xVYHQ3ci .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PODTh9I8xVYHQ3ci .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PODTh9I8xVYHQ3ci .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PODTh9I8xVYHQ3ci :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

jar 起不来

起来了但访问不对

能访问但会自己断

部署后访问失败

报错出现在哪一层?

启动层

反代层

证书层

UnsupportedClassVersionErrorclass file version 61.0

堆栈类名以 javax 开头

nohup 挂进程,终端一断就没了

HTTPS 和 HTTP 之间来回跳

上传稍大文件就 413

WebSocket 握手失败

curl -v 分层排查

证书到期后整站打不开

修法:换 JDK 17+ 绝对路径

修法:javax 依赖升级,导入改 jakarta

修法:宝塔项目管理或 systemd 托管

修法:Nginx 传转发头应用声明信任转发头

修法:放大 client_max_body_size与 multipart 上限

修法:透传 Upgrade 与 Connection 头

按 curl 返回码定位:refused / 502 / 504

修法:续期后执行 Nginx reload

启动层,jar 起不来

1. UnsupportedClassVersionError,class file version 61.0

报错:

java.lang.UnsupportedClassVersionError: com/example/App has been compiled
by a more recent version of the Java Runtime (class file version 61.0),
this version of the Java Runtime only recognizes class file versions up to 55.0

机制:Spring Boot 3.x 要求 Java 17 起步,编译出的 class 文件版本号是 61.0。低版本 JVM 只认得更低的版本号,加载时直接拒绝。报错里写着只认到 55.0,对应的是 Java 11,说明启动脚本实际用的 JVM 是 JDK 11。机器上装着多个 JDK 时,宝塔生成的启动脚本或 systemd 服务没有写死 JDK 路径,就会用到默认那个。

修法:把启动命令里的 java 换成 JDK 17 以上版本的绝对路径,例如 /usr/lib/jvm/jdk-17/bin/java -jar app.jar。用 systemd 托管时把绝对路径写进 unit 文件的 ExecStart。

自查:在启动脚本实际使用的环境里跑 java -version,确认版本是 17 或更高。class 文件版本号按 JVM 规范核对,61 对应 Java 17,55 对应 Java 11,52 对应 Java 8。

2. 堆栈里的类名以 javax 开头

报错:java.lang.ClassNotFoundException: javax.servlet.Filter,或者同类的 NoClassDefFoundError,出错的类名以 javax 开头。

机制:Spring Boot 3 基于 Jakarta EE 10,Servlet 系列的包名从 javax 换成了 jakarta,内嵌的 Tomcat 10.1 只带 jakarta 的类。还引用 javax 的老依赖在 Boot 3 上找不到类。老版本的过滤器、鉴权库,以及自己写的 Filter、Servlet、监听器,是常见的出错点。

修法:升级还挂在 javax 上的依赖,把自己代码里的 javax.servlet 导入改成 jakarta.servlet。

自查:先看堆栈里的类名前缀。类名以 javax 开头的是这层问题,类名已经是 jakarta 开头就往别处查。

启动这层还有一个不报错的问题。用 nohup 把进程挂在 SSH 会话里,终端一断进程就没了,日志还会无限涨。用宝塔的项目管理或 systemd 托管,把启动命令、自动拉起和日志路径固定下来。前者省事,后者离开面板还能带走,按这台机器以后归谁维护来选。

反代层,起来了但访问不对

3. 在 HTTPS 和 HTTP 之间来回跳

机制:Nginx 在 443 终结 TLS,转发给应用的请求是 HTTP。应用按请求的 scheme 生成跳转地址时看到的是 HTTP,一跳就掉出 HTTPS。浏览器里表现为重定向被拦截,或者页面混着 HTTP 资源被拦掉,样式丢失。

修法:Nginx 侧传转发头,应用侧声明信任转发头。

location / {
proxy_pass http://127.0.0.1:8080;
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;
}

server:
forward-headers-strategy: native

自查:curl -I https://你的域名/某个会触发跳转的地址,看 Location 头里的协议是 HTTPS 还是 HTTP。

4. 上传稍大的文件就 413

报错:413 Request Entity Too Large。

机制:Nginx 的 client_max_body_size 默认值是 1m,Spring 的 multipart 也有自己的上限。请求要连过两道门槛,哪一道先拦住都算数,只放行其中一处没有用。

修法:在反代配置的 server 或 location 里设 client_max_body_size 50m;,同步放大应用侧的 spring.servlet.multipart.max-file-size 和 max-request-size。

自查:nginx -T | grep client_max_body_size 看生效值。两处限制谁小谁说了算,改完再看一次。

5. WebSocket 握手失败

报错特征:浏览器开发者工具的网络面板里,WebSocket 请求握手返回 400 或 502。只看页面会以为功能坏了,状态码藏在开发者工具里。

机制:WebSocket 握手带 Upgrade 和 Connection 两个头,Nginx 默认按普通请求转发,不透传它们,握手到不了应用。

修法:在 Nginx 的 http 段定义 map,在反代的 location 里透传这两个头。

map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

location /ws {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}

自查:面板生成的反代配置里如果没有这两行 proxy_set_header,补上再 reload。

6. 不通的时候先分清谁拒绝了你

改完配置还是不通,curl -v 是分层的第一件工具。返回 connection refused,说明 443 或 80 没有人监听,去查防火墙和安全组。宝塔的安全页管一层,云厂商的安全组管另一层,两层都要放行 80 和 443。返回 502 Bad Gateway,说明 nginx 活着,转发的上游不通,对比反代的 proxy_pass 端口和应用实际监听的 server.port。返回 504 Gateway Time-out,说明上游太慢,去反代的读超时设置里找。

把 curl -v 的返回码和对应排查方向画成一张图,方便对照:

#mermaid-svg-QLglpqdq9UpYo0em{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QLglpqdq9UpYo0em .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QLglpqdq9UpYo0em .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QLglpqdq9UpYo0em .error-icon{fill:#552222;}#mermaid-svg-QLglpqdq9UpYo0em .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QLglpqdq9UpYo0em .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QLglpqdq9UpYo0em .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QLglpqdq9UpYo0em .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QLglpqdq9UpYo0em .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QLglpqdq9UpYo0em .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QLglpqdq9UpYo0em .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QLglpqdq9UpYo0em .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QLglpqdq9UpYo0em .marker.cross{stroke:#333333;}#mermaid-svg-QLglpqdq9UpYo0em svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QLglpqdq9UpYo0em p{margin:0;}#mermaid-svg-QLglpqdq9UpYo0em .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-QLglpqdq9UpYo0em .cluster-label text{fill:#333;}#mermaid-svg-QLglpqdq9UpYo0em .cluster-label span{color:#333;}#mermaid-svg-QLglpqdq9UpYo0em .cluster-label span p{background-color:transparent;}#mermaid-svg-QLglpqdq9UpYo0em .label text,#mermaid-svg-QLglpqdq9UpYo0em span{fill:#333;color:#333;}#mermaid-svg-QLglpqdq9UpYo0em .node rect,#mermaid-svg-QLglpqdq9UpYo0em .node circle,#mermaid-svg-QLglpqdq9UpYo0em .node ellipse,#mermaid-svg-QLglpqdq9UpYo0em .node polygon,#mermaid-svg-QLglpqdq9UpYo0em .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QLglpqdq9UpYo0em .rough-node .label text,#mermaid-svg-QLglpqdq9UpYo0em .node .label text,#mermaid-svg-QLglpqdq9UpYo0em .image-shape .label,#mermaid-svg-QLglpqdq9UpYo0em .icon-shape .label{text-anchor:middle;}#mermaid-svg-QLglpqdq9UpYo0em .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QLglpqdq9UpYo0em .rough-node .label,#mermaid-svg-QLglpqdq9UpYo0em .node .label,#mermaid-svg-QLglpqdq9UpYo0em .image-shape .label,#mermaid-svg-QLglpqdq9UpYo0em .icon-shape .label{text-align:center;}#mermaid-svg-QLglpqdq9UpYo0em .node.clickable{cursor:pointer;}#mermaid-svg-QLglpqdq9UpYo0em .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QLglpqdq9UpYo0em .arrowheadPath{fill:#333333;}#mermaid-svg-QLglpqdq9UpYo0em .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QLglpqdq9UpYo0em .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QLglpqdq9UpYo0em .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QLglpqdq9UpYo0em .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QLglpqdq9UpYo0em .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QLglpqdq9UpYo0em .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QLglpqdq9UpYo0em .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QLglpqdq9UpYo0em .cluster text{fill:#333;}#mermaid-svg-QLglpqdq9UpYo0em .cluster span{color:#333;}#mermaid-svg-QLglpqdq9UpYo0em div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QLglpqdq9UpYo0em .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QLglpqdq9UpYo0em rect.text{fill:none;stroke-width:0;}#mermaid-svg-QLglpqdq9UpYo0em .icon-shape,#mermaid-svg-QLglpqdq9UpYo0em .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QLglpqdq9UpYo0em .icon-shape p,#mermaid-svg-QLglpqdq9UpYo0em .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QLglpqdq9UpYo0em .icon-shape .label rect,#mermaid-svg-QLglpqdq9UpYo0em .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QLglpqdq9UpYo0em .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QLglpqdq9UpYo0em .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QLglpqdq9UpYo0em :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

connection refused

502 Bad Gateway

504 Gateway Time-out

curl -v 访问不通

返回什么?

443 / 80 无人监听

查宝塔安全页放行 80 / 443

查云厂商安全组放行 80 / 443

Nginx 活着,上游不通

对比 proxy_pass 端口与应用 server.port

上游响应太慢

调反代读超时设置

证书层,能访问但会自己断

7. 证书到期后整站突然打不开

机制:HTTPS 证书有效期有限,到期后浏览器直接拒绝连接。自动续期任务跑完,还要让 Nginx 重新加载配置,否则服务用的还是内存里的旧证书。

修法:用面板的证书自动续期或 Certbot 的定时任务,确认续期后的动作里有 Nginx reload 这一步。

自查:echo | openssl s_client -connect 你的域名:443 -servername 你的域名 2>/dev/null | openssl x509 -noout -dates,看 notAfter 离现在还有多久。具体有效期以签发方公布为准,这些年行业里的方向是越来越短,别按某一篇教程记死天数。

适用边界

清单里的版本事实固定在 Spring Boot 3.2 这一代,换到 4.x 或者更老的 2.x,要重新对一遍要求。面板的界面、生成的配置和证书功能随版本变化,写到面板的地方以你的版本为准。这份清单整理自公开文档和常见报错,没有在宝塔上实机跑完一整条流程,每条都留了自查命令,方便你逐条对照。应用本身的业务异常、性能和安全加固不在这份清单里,报错落不到上面几层时,问题多半在应用自己身上。

赞(0)
未经允许不得转载:网硕互联帮助中心 » 宝塔部署SpringBoot3.2到HTTPS的坑清单
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!