本地部署正常;服务器部署 POST 方法参数丢失解决方案 📅 2026/6/19 10:28:59 本地部署正常服务器部署 POST 方法参数丢失解决方案背景同一套 JAR 代码本地127.0.0.1:6060直连测试正常部署到服务器后通过域名http://web.mycdn66.com调用时POST 请求 body 中的参数丢失接口返回{msg:无效参数,ok:false}。本文档记录问题原因及解决方案。问题问题现象环境访问方式参数位置结果本地http://127.0.0.1:6060/...POST body正常服务器http://web.mycdn66.com/...POST body参数丢失返回「无效参数」服务器http://web.mycdn66.com/...?mobile...URL 查询字符串正常服务器https://web.mycdn66.com/...POST body正常问题描述通过http://访问域名并发送POST请求参数在 body 中如multipart/form-data时接口返回{msg:无效参数,ok:false}。改为https://或把参数放在 URL 查询字符串上则正常。该问题与后端框架无关TIO / Spring Boot / JFinal 均可能遇到根因在Nginx 的 HTTP→HTTPS 跳转与HTTP 客户端对 301 的处理方式。复现步骤失败Unirest.post(http://web.mycdn66.com/mytio/sms/beforeCheck.tio_x).multiPartContent().field(p_is_android,1).field(_lau,cn).field(biztype,2).field(mobile,15837827991).asString();响应{msg:无效参数,ok:false}与本项目相关的代码接口路径/mytio/sms/beforeCheck.tio_x控制器SmsController.beforeCheckRequestPath(value/beforeCheck)publicRespbeforeCheck(Bytebiztype,Stringmobile,HttpRequestrequest)throwsException{returnbizPhoneCheck(biztype,mobile,request);}publicstaticRespbizPhoneCheck(Bytebiztype,Stringmobile,HttpRequestrequest){if(biztypenull||mobilenull){returnResp.fail().msg(RetUtils.INVALID_PARAMETER);// 无效参数}// ...}当biztype或mobile为null时返回无效参数说明参数没有到达 Java 应用而非业务逻辑错误。根因分析请求链路对比访问方式实际路径是否有 301 跳转POST Bodyhttp://web.mycdn66.com/...客户端 → Nginx → 301 → 客户端 → Nginx → Java有可能在跳转时丢失https://web.mycdn66.com/...客户端 → Nginx → Java无正常到达http://127.0.0.1:6060/...客户端 → Java无正常到达301 是什么301 Moved Permanently表示资源已永久迁移到新地址。Nginx 常见配置server { listen 80; server_name web.mycdn66.com; return 301 https://$host$request_uri; }访问http://时Nginx不会把请求转发给 Java而是直接返回 301告诉客户端去https://再请求一次。为什么会丢 Body第 1 次POST http://域名/xxx body 含 mobile、biztype 第 2 次Nginx 返回 301 → Location: https://域名/xxx 第 3 次客户端再 POST https://域名/xxx 很多 HTTP 客户端Unirest、Apifox、部分 HttpClient在 301/302 跳转时 不会把原来的 POST body 再发一遍 第 4 次Java 收到空 body → biztype、mobile 为 null → 无效参数注意Nginx不会主动把参数改成nullJava不会因为框架不同而免疫Spring Boot 同样会遇到问题发生在请求到达 Java 之前为什么 URL 传参不受影响301 跳转时新 URL 会保留 query stringhttp://域名/xxx?mobile15837827991biztype2 ↓ 301 https://域名/xxx?mobile15837827991biztype2URL 上的参数会保留所以即使用http://也能成功。为什么本地 127.0.0.1 正常本地直连127.0.0.1:6060不经过 Nginx没有 301 跳转POST body 一次到达 Java。为什么「同一个 JAR」表现不同JAR 代码相同但本地测试127.0.0.1:6060直连远程测试web.mycdn66.com经 Nginx且使用http://环境链路不同不是代码不一致。HTTP 状态码对比状态码含义POST Body 是否保留取决于客户端301永久跳转很多客户端不保留302临时跳转很多客户端不保留307临时跳转方法不变应保留308永久跳转方法不变应保留常见误解误解实际情况JAR 代码和服务器不一致同一 JAR链路不同直连 vs 经 Nginx 301JFinal 需要先getFile()才能getPara()本项目 HTTP 层是 TIO不是 JFinal MVCNginx 把参数改成了 nullNginx 未转发或客户端跳转时未带 bodyJava 读不到参数Spring Boot 不会有这个问题任何框架都会在 body 未到达时得到 null只有 multipart 会出问题任何 POST bodyJSON、表单、文件都可能受影响问题结论本地正常、服务器异常不是 JAR 代码不一致而是请求链路不同本地直连 vs 服务器经 Nginx根因Nginx 301 跳转 HTTPS客户端跳转时未保留 POST body验证改为https://后问题消失性质非 Java 代码问题属 HTTP 跳转与客户端行为问题解决方案方案 1客户端统一使用 HTTPS推荐已验证有效将所有http://web.mycdn66.com改为https://web.mycdn66.com。Unirest.post(https://web.mycdn66.com/mytio/sms/beforeCheck.tio_x).header(Cookie,tio_session...).multiPartContent().field(p_is_android,1).field(_lau,cn).field(biztype,2).field(mobile,15837827991).asString();注意不要手动设置Content-Type: multipart/form-data; boundary...交给.multiPartContent()自动生成Apifox、移动端、第三方调用方均需统一改为https://方案 2参数放 URL 查询字符串适用于无文件上传的普通参数接口Unirest.post(https://web.mycdn66.com/mytio/sms/beforeCheck.tio_x?p_is_android1_laucnbiztype2mobile15837827991).header(Cookie,tio_session...).asString();无需.multiPartContent()。方案 3普通表单代替 multipart无文件时Unirest.post(https://web.mycdn66.com/mytio/sms/beforeCheck.tio_x).field(p_is_android,1).field(_lau,cn).field(biztype,2).field(mobile,15837827991).asString();不调用.multiPartContent()使用application/x-www-form-urlencoded。方案 4Nginx 改用 307 跳转服务端兜底将 301 改为 307要求客户端跳转时保留 POST 方法和 bodyserver { listen 80; server_name web.mycdn66.com; return 307 https://$host$request_uri; }改完后执行nginx-tsystemctl reload nginx方案 580 端口 API 直接代理不跳转对 API 路径在 80 端口直接proxy_pass仅页面对用户做 http→https 跳转upstream tio_site_api { server 127.0.0.1:6060; keepalive 32; } server { listen 80; server_name web.mycdn66.com; client_max_body_size 200m; location /mytio/ { proxy_pass http://tio_site_api; 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; proxy_http_version 1.1; proxy_set_header Connection ; } location / { return 301 https://$host$request_uri; } }注意HTTP 明文传输安全性较低生产环境仍建议客户端优先使用 HTTPS。验证步骤在服务器上执行# 1. 直连 Java应成功curl-v-XPOSThttp://127.0.0.1:6060/mytio/sms/beforeCheck.tio_x\-HCookie: tio_session你的session\-Fp_is_android1-F_laucn-Fbiztype2-Fmobile15837827991# 2. 走域名 HTTP可能因 301 丢 body 而失败curl-v-XPOSThttp://web.mycdn66.com/mytio/sms/beforeCheck.tio_x\-HCookie: tio_session你的session\-Fp_is_android1-F_laucn-Fbiztype2-Fmobile15837827991# 3. 走域名 HTTPS应成功curl-v-XPOSThttps://web.mycdn66.com/mytio/sms/beforeCheck.tio_x\-HCookie: tio_session你的session\-Fp_is_android1-F_laucn-Fbiztype2-Fmobile15837827991观察第 2 步是否出现301 Moved Permanently以及第 3 步是否返回{ok:true}。推荐实践所有客户端、Apifox、App 统一使用https://Nginx 将return 301改为return 307作为兜底无文件上传的接口优先用 URL 参数或x-www-form-urlencoded不要手动写 multipart 的Content-Typeboundary相关文件部署说明DEPLOY.mdNginx 配置示例接口代码http-server-api/src/main/java/org/tio/sitexxx/web/server/controller/base/sms/SmsController.java运行时配置all/src/main/resources/app-env.propertieshttp.isproxiedtrue