如何部署 SurveyKing Pro
SurveyKing Pro 由 MySQL、Redis、Java 后端和两套前端入口组成。生产环境建议只对外开放 Nginx 的 HTTP/HTTPS 端口,后端、数据库和 Redis 仅允许本机或受信网络访问。
选择部署方式
| 场景 | 推荐方式 | 说明 |
|---|---|---|
| 第一次部署、希望使用图形界面 | 宝塔部署 | 通过宝塔安装软件、管理 Java 项目和配置站点 |
| 已有 Docker 运维体系 | Docker Compose 部署 | 使用容器统一管理 MySQL、Redis、后端和 Nginx |
| 使用 Rocky Linux、AlmaLinux 等 RHEL 8 系统 | RHEL 8 系部署 | 使用 systemd 管理后端服务 |
| 多台应用服务器 | 分布式部署 | 使用共享数据库、Redis、对象存储和负载均衡 |
必须通过 /survey/ 等子路径访问 | 二级目录部署 | 需要匹配的前端构建产物和 Nginx 配置 |
下面给出标准单机部署流程。不同版本的交付文件名可能略有差异,以实际交付包为准。
部署前准备
服务器要求
- Linux x86_64 服务器,建议至少 2 核 CPU、4 GB 内存和 20 GB 可用磁盘。
- Java 8 运行环境。
- MySQL 5.7 或 8.0。
- Redis 6 或 7。
- Nginx stable 版本。
- 已备案域名和 HTTPS 证书(公网生产环境)。
交付文件
surveyking-server.jar:后端程序。surveyking-pro.sql:数据库初始化脚本。- 前端压缩包:解压后应包含
dist/public/index.html和dist/admin/index.html。 - 版本随附的配置说明、License 或其他授权文件。
建议使用以下目录:
/opt/surveyking/
├── server/surveyking-server.jar
├── client/dist/public/
├── client/dist/admin/
├── config/application.yml
├── files/
└── logs/
1. 初始化数据库
使用独立数据库账号,不要让应用连接 MySQL root 账号。
CREATE DATABASE survey
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
CREATE USER 'surveyking'@'127.0.0.1' IDENTIFIED BY '请替换为强密码';
GRANT ALL PRIVILEGES ON survey.* TO 'surveyking'@'127.0.0.1';
FLUSH PRIVILEGES;
导入交付的初始化脚本。-p 后不要直接写密码,按提示输入即可。
mysql -h 127.0.0.1 -u surveyking -p survey < surveyking-pro.sql
已有正式数据的数据库不要重复导入初始化脚本。升级前先完成数据库和附件备份,再按版本升级说明执行。
2. 配置并启动后端
将交付包中的配置文件作为基础配置,仅在外部文件中覆盖当前环境的端口、数据库和 Redis 连接。不要把真实密码提交到代码仓库。
server:
port: 48080
spring:
datasource:
dynamic:
datasource:
master:
name: survey
url: jdbc:mysql://127.0.0.1:3306/survey?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
username: surveyking
password: '请替换为数据库密码'
redis:
host: 127.0.0.1
port: 6379
database: 0
# Redis 未设置密码时删除下一行。
password: '请替换为 Redis 密码'
首次启动时在前台查看日志:
cd /opt/surveyking/server
java -jar surveyking-server.jar \
--spring.profiles.active=prod \
--spring.config.additional-location=optional:file:/opt/surveyking/config/
出现启动成功日志后,再使用 systemd、宝塔或 Docker 管理进程。不要长期使用 nohup 代替服务管理器。
完成标志: 48080 端口仅监听在预期网卡上,应用日志中没有数据库、Redis 或 License 错误。
3. 部署前端文件
解压前端包,并确认两个入口文件都存在:
unzip surveyking-fe.zip -d /opt/surveyking/client
test -f /opt/surveyking/client/dist/public/index.html
test -f /opt/surveyking/client/dist/admin/index.html
如果压缩包内已经包含顶层目录,应根据实际结构调整解压目标,最终目录必须与 Nginx 配置一致。
4. 配置 Nginx
以下配置依据当前根目录生产配置整理。将域名、前端目录和后端地址替换为实际值。map 必须放在 Nginx 的 http {} 中,不能放进 server {};主配置已经存在同名 map 时不要重复添加。
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name survey.example.com;
index index.html;
client_max_body_size 100m;
location = /pub {
return 301 /pub/;
}
location = /adm {
return 301 /adm/;
}
# 入口 HTML 不缓存,避免升级后继续引用旧版资源。
location = /pub/index.html {
root /opt/surveyking/client/dist/public;
etag off;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
try_files /index.html =404;
}
location = /adm/index.html {
root /opt/surveyking/client/dist/admin;
etag off;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
try_files /index.html =404;
}
# 带 hash 的构建资源可以长期缓存。
location ^~ /pub/ {
alias /opt/surveyking/client/dist/public/;
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
}
location ^~ /adm/ {
alias /opt/surveyking/client/dist/admin/;
expires 1y;
add_header Cache-Control "public, max-age=31536000, immutable";
}
# 答题、练习、公开查询、数据分享和兑换页面使用 public 入口。
location ~ ^/(e|s|t|q|share|redeem)(/|$) {
root /opt/surveyking/client/dist/public;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
try_files /index.html =404;
}
# 登录、注册和绑定页面使用 public 入口。
location ~ ^/user/(login|register|binding)/?$ {
root /opt/surveyking/client/dist/public;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
try_files /index.html =404;
}
location ^~ /captcha {
proxy_pass http://127.0.0.1:48080;
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 Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 1800s;
}
location ^~ /admin-api {
proxy_pass http://127.0.0.1:48080;
proxy_buffering off;
proxy_cache off;
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 Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 60s;
proxy_read_timeout 1800s;
proxy_send_timeout 1800s;
}
location = /health {
access_log off;
add_header Content-Type text/plain;
return 200 "healthy\n";
}
# 其他页面使用后台入口。
location / {
root /opt/surveyking/client/dist/admin;
add_header Cache-Control "no-cache, no-store, must-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
try_files $uri $uri/ /index.html;
}
}
前端路由归属
生产构建包含 public 和 admin 两套 SPA。Nginx 必须先匹配 public 页面,再将其他页面回退到 admin 入口。
| 构建入口 | 页面路由 | Nginx 处理 |
|---|---|---|
| public | /e/:id、/s/*、/t/*、/q/:publicCode、/share/:publicCode、/redeem/:projectId | 匹配 `^/(e |
| public | /user/login、/user/register、/user/binding | 使用独立的 /user/ 精确匹配并返回 dist/public/index.html |
| admin | /preview、管理后台及其他已配置页面 | 最后的 location / 返回 dist/admin/index.html |
/s/* 已包含答卷、考试结果、维度报告、证书、抽奖、打印和投票排行等子路由。OAuth2 授权接口使用 /admin-api/system/oauth2/authorize,不是前端 /authorize 页面。新增 public 页面时,应同时更新前端 publicRoutes、根目录 Nginx 规则和二级目录 Nginx 规则。
/files 路径只有旧版本的文件域名仍使用 /files 时,才需要为该路径增加到后端 48080 的反向代理。新部署优先在管理后台配置对象存储或本地文件服务域名。
配置 HTTPS 时复用同一组 location,不要同时保留两个内容不同的 HTTP/HTTPS 站点配置。TLS 证书路径以实际证书文件为准,并仅启用组织允许的 TLS 版本。
5. 验证部署
# 检查服务和端口
ss -lntp | grep -E ':(3306|6379|48080|80|443)\b'
# 检查 Nginx 配置
nginx -t
systemctl reload nginx
# 检查两个前端入口、public history fallback 和健康检查
curl -I http://127.0.0.1/pub/index.html
curl -I http://127.0.0.1/adm/index.html
curl -I http://127.0.0.1/e/route-check
curl -I http://127.0.0.1/s/route-check
curl -I http://127.0.0.1/t/route-check
curl -I http://127.0.0.1/q/route-check
curl -I http://127.0.0.1/share/route-check
curl -I http://127.0.0.1/redeem/route-check
curl -I http://127.0.0.1/user/login
curl http://127.0.0.1/health
上述测试码不需要对应真实数据;此处只检查 Nginx 是否返回 public 入口 HTML,预期 HTTP 状态为 200。实际页面随后调用业务接口时,可能因测试码不存在而显示业务提示。
再使用普通账号完成一次登录、创建测试项目、提交答卷和上传文件。管理员能打开后台,不代表答题入口、文件域名和权限配置都正确。
6. 上线后配置
进入管理后台完成以下设置:
- 配置文件存储,并验证上传、预览和下载。
- 设置系统访问域名、注册开关和验证码。
- 按需配置企业微信、微信公众号、钉钉、邮件或短信。
- 配置 License,并确认授权用户数和有效期。
- 备份数据库、附件、配置文件和 License,保存恢复步骤。
常见问题
页面可以打开,但接口返回 404
检查 Nginx 是否将 /admin-api 和 /captcha 原样转发到 48080,不要在 proxy_pass 中意外增加或删除路径前缀。
升级后页面空白或仍显示旧版本
确认 index.html 使用 no-cache,构建资源目录与新版本一致,并清理 CDN 或上游代理中的旧 HTML 缓存。
后端可以启动,但上传文件后无法访问
检查管理后台中的文件配置、存储目录写权限和对外访问域名。分布式部署不能使用各节点互不共享的本地目录。