← 返回导航
后端技术架构
v1.0 · 2026-08-01
版本:v1.1(2026-08-16,评审后同步:12 表 / 阿里云短信 / 存储抽象 / WS 鉴权)
服务端环境:CentOS 7.9 / 4核 3.6G / Java 17.0.19 / PostgreSQL 15.17(已在跑)
1. 技术栈决策
| 决策点 | 选择 | 理由 |
|---|
| 语言 | Java 17(Temurin) | 服务器已装 17.0.19,Spring Boot 3.x 官方要求 |
| 框架 | Spring Boot 3.3.x | 用户 Java 主栈(EAH 同栈),生态成熟 |
| ORM | MyBatis-Plus 3.5.7 | 用户 EAH 项目已用(JPA→MP 迁移经验),BaseMapper 免写 SQL |
| 数据库 | PostgreSQL 15.17(PGDG,已在跑) | 服务器现成实例(5432 监听);JSONB 原生支持(milestones);EAH 同款 |
| 认证 | JWT(jjwt 0.12.x) | 无状态、简单;登录后下发 token(30 天);拦截器查库校验用户状态(2026-08-16 起) |
| 短信验证码 | 阿里云号码认证·短信认证(TIMESAKE_SMS_TYPE=aliyun,2026-08-12 定案) | 个人资质可用、无需企业签名/模板审批;开发期可切 mock(固定码 123456) |
| 实时同步 | Spring WebSocket(原生) | 项目级频道 /ws/projects/{id}?token=,JSON 消息协议(见 api.md);握手鉴权 JWT + 项目权限(2026-08-16 修复评审 P0) |
| 推送 | 华为 Push Kit(二期接入) | 鸿蒙端唯一推送通道,需 AGC 配置;MVP 先做本地提醒 |
| API 文档 | SpringDoc OpenAPI(swagger-ui) | 自动生成接口文档,联调自测方便 |
| 部署 | fat jar + systemd(MVP) | 内存友好(3.6G 总内存)、运维简单;后续可容器化 |
| 缓存 | 无(MVP) | 验证码存 DB(sms_code 表);流量上来后再加 Redis |
| 图片存储 | ObjectStorage 抽象:local(默认)/ oss / cos | @ConditionalOnProperty 装配;云密钥缺失启动即失败不静默降级 |
| 工程结构 | 单模块 Maven | 规模可控,按包分层,避免过度设计 |
2. 架构图
鸿蒙 App(念时 · ArkTS/ArkUI)+ H5/微信小程序(uni-app)
│ HTTPS (REST /api/v1/**)
│ WSS (/ws/projects/{id}?token=<jwt>)
▼
┌─────────────────────────────────────────┐
│ timesake-server(Spring Boot 3.3) │
│ ┌───────────────────────────────────┐ │
│ │ Controller 层(REST + WS 端点) │ │
│ │ Auth / Project / Record / Todo / │ │
│ │ Share / Invite / Bg / Upload │ │
│ │ + WsEndpoint │ │
│ ├───────────────────────────────────┤ │
│ │ Service 层(业务 + 事务 + 权限) │ │
│ │ AuthService / SmsService / │ │
│ │ WeixinService / ProjectService / │ │
│ │ RecordService / TodoService / │ │
│ │ ShareService / InviteService / │ │
│ │ BgPresetService / ImageCompressor│ │
│ ├───────────────────────────────────┤ │
│ │ Mapper 层(MyBatis-Plus) │ │
│ │ UserMapper / ProjectMapper / ... │ │
│ ├───────────────────────────────────┤ │
│ │ 拦截器:JWT 认证(查库校验用户状态) │ │
│ └───────────────────────────────────┘ │
└──────────────┬──────────────────────────┘
│ JDBC + WebSocket 会话
▼
PostgreSQL 15.17(timesake 库,12 张表)
3. 工程目录结构
timesake-server/
├── pom.xml # Spring Boot 3.3 + MP 3.5.7 + jjwt + springdoc + 阿里云 dypnsapi
├── src/main/java/com/timesake/
│ ├── TimesakeApplication.java
│ ├── config/ # WebConfig / WebSocketConfig / MybatisPlusConfig / JwtInterceptor
│ ├── controller/ # Auth / Project / Record / Todo / Share / Invite / Bg / Upload
│ ├── service/ # 业务逻辑(Auth / Sms / Weixin / Project / Record / Todo / Share / Invite / BgPreset)
│ ├── mapper/ # MyBatis-Plus Mapper 接口(12 表各一)
│ ├── entity/ # PO(@TableName 映射)
│ ├── dto/ # 请求/响应对象(ProjectDtos / AuthDtos / RecordDtos / TodoDtos)
│ ├── storage/ # ObjectStorage 接口 + local / oss / cos 实现 + StorageProperties
│ ├── ws/ # WebSocket 端点(WsEndpoint,握手鉴权)
│ ├── common/ # 统一响应 R<T> / 错误码 / BizException / 全局异常处理 / ImageCompressor
│ └── util/ # JwtUtil / UserContext
├── src/main/resources/
│ ├── application.yml # 数据源 / JWT / 短信 / 微信 / 存储 / 前端域名配置
│ ├── db/init.sql # 建库建表脚本(12 张表 + 幂等迁移段)
│ └── static/bg/ # 内置预设背景(bg-<id>.jpg)
└── server.log # 运行日志(排查 500 用)
4. 关键设计
4.1 统一响应
{ "code": 0, "message": "ok", "data": {...} }
- code=0 成功;错误码分段:100x 认证(1005=token 失效)/ 200x 权限 / 300x 项目 / 400x 参数 / 500x 微信登录 / 41xx 待办分享一念(见 api.md)
4.2 认证流程
1. POST /auth/sms/send {phone} → 阿里云短信认证下发验证码(60s 限频,5min 有效,存 sms_code 表;
连续错误 5 次锁 15 分钟,2026-08-16 应用层兜底)
2. POST /auth/login {phone, code} → 校验 → 签发 JWT(30 天)→ 返回 {token, user}
POST /auth/wx-login {code} → 微信小程序 code2session → openid 登录/注册
3. 后续请求带 Authorization: Bearer *** → JwtInterceptor 解析 + 查库校验用户存在且未禁用
4.3 实时同步(WebSocket)
- 连接:
wss://host/ws/projects/{projectId}?token=;握手校验 JWT + 项目权限(进行中/珍藏需成员;一念需成员或已「看见」的参与档案) - 服务端广播事件:record_added / record_deleted / member_joined / project_updated / todo_added / todo_toggled / wish_updated / suggestion_commented
- 客户端心跳:每 30s
{"type":"ping"}(H5 发字符串、小程序发 {data},2026-08-16 修复) - 单机部署用本地 WebSocket 会话表;将来多实例换 Redis Pub/Sub
4.4 伙伴加入(邀请)
1. 管理员 POST /projects/{id}/invite → 生成 token(UUID,7 天有效)
2. 好友端扫码/链接 → POST /projects/join {token} → 加入项目(幂等);一念项目仅留「看见」档案
3. WebSocket 广播 member_joined → 所有伙伴刷新成员列表
4.5 数据库(12 张表,详见 database.md)
user / project / project_member / project_record / invite / sms_code / todo / share / wish_participant(一念参与档案)/ wish_suggestion(一念建议)/ wish_suggestion_support(附议)/ wish_suggestion_comment(留言,两层)
5. 部署方案(MVP)
1. 建库建表:psql -f init.sql(PostgreSQL 15.17,timesake 库)
2. 打包:mvn -DskipTests package → timesake-server.jar
3. systemd 常驻(/etc/systemd/system/timesake.service):
- ExecStart=/usr/bin/java -Xms256m -Xmx512m -jar timesake-server.jar --server.port=18080
- Environment:TIMESAKE_DB_PASSWORD / TIMESAKE_JWT_SECRET / TIMESAKE_SMS_TYPE=aliyun /
TIMESAKE_SMS_ALIYUN_* / TIMESAKE_WX_APPID / TIMESAKE_WX_SECRET(密钥只写 systemd,不进仓库)
- Restart=always,开机自启
4. 端口:**18080**(REST + WebSocket 同端口;8080 已被 EAH Docker 占用,勿用)
- REST 前缀:/api/v1/*;WebSocket:/ws/projects/{projectId}?token=<jwt>
5. 反向代理:nginx 挂域名 **timesake-api.shihesuian.cn** → 127.0.0.1:18080(HTTPS,已部署)
- /ws/ 走 upgrade 长连接(proxy_read_timeout 3600s)
6. H5 端静态站点:nginx 托管 **timesake.shihesuian.cn** → /data/timesake-h5/(HTTPS,已部署)
- 构建:`cd h5 && npm run build:h5`,产物在 h5/dist/build/h5/,拷贝到 /data/timesake-h5/(chmod -R 755)
- 域名已收敛到 h5/src/utils/config.ts(API_BASE / API_DOMAIN / WS_BASE / H5_BASE)
7. 本地实测:验证码 → 登录链路已通(mock 验证码 123456 / 生产阿里云)
6. 二期预留
| 项 | 方案 |
|---|
| Redis 缓存/验证码 | spring-data-redis,替换 DB 存储 |
| 华为 Push Kit | AGC 配置 + PushService 调 HMS Push API |
| 云存储 delete | OSS/COS 实现 ObjectStorage.delete(当前 local 已实现,云实现静默跳过) |
| 多实例 | WebSocket 会话改 Redis Pub/Sub,水平扩展 |
| 容器化 | Dockerfile + docker-compose(现有 Docker 26.1.4 支持) |
| 数据统计 | value_json 聚合查询(JSONB),生长曲线图接口 |