7.4 KiB
7.4 KiB
LPT 后端服务(lpt-be)
Java Spring Boot 后端,提供 REST API、数据库访问、认证鉴权。
Git 提交规范
- 提交信息必须简短且使用中文,不要使用英文长句。
- 格式:
类型: 简述,例如feat: 新增用户登录接口、fix: 修复多租户拦截器空指针、docs: 补充API文档。
技术栈
- Java 17
- 框架:Spring Boot 3.2.5
- ORM:MyBatis-Plus 3.5.5
- 数据库:MySQL 8.0
- 认证:Sa-Token 1.38.0,Cookie 名
satoken - 数据库迁移:Flyway
- 对象映射:MapStruct 1.5.5
- 连接池:Druid 1.2.8
- 密码加密:jBCrypt 0.4
- API 文档:Knife4j (OpenAPI 3)
- Lombok(@Data, @Slf4j)
项目结构
lpt-be/src/main/java/com/guo/learningprogresstracker/
├── controller/ → REST 接口层
├── service/ → 业务逻辑层(接口 + impl)
├── mapper/ → MyBatis-Plus BaseMapper
├── entity/ → 数据库实体
├── dto/ → 请求/响应 DTO
├── config/ → Spring 配置
├── common/ → 全局异常处理、Ops
├── mapStruct/ → MapStruct Converter
├── enums/ → 枚举类
├── exception/ → 自定义异常
└── utils/ → 工具类
- controller 只做参数校验和路由。
- service/impl 承载业务逻辑。
- mapper 使用 MyBatis-Plus BaseMapper。
- entity 使用
@TableName、@TableField映射数据库字段。 - mapStruct 承载 DTO 转换。
API 端点总览(32 个)
| 模块 | 端点数 | 端点 |
|---|---|---|
| 学习会话 | 9 | POST /study-sessions/{taskNum}/start, PUT .../pause, PUT .../resume, PUT .../end, POST .../fragments, GET .../history, PUT .../expectation, GET .../expectation, GET .../report-draft |
| 标准思维导图 | 6 | GET /review/standard-mind-map/{taskNum}, POST .../regenerate, PUT ..., POST .../recall, POST .../find-node, GET .../recall-records |
| 复习模块 | 6 | GET /review/feed, GET /review/task/{taskNum}, GET /review/report/{id}, GET /review/fragment/{id}, GET /review/standard-mind-map/recall-records/{recordId}, GET /review/tasks |
| 任务管理 | 6 | GET /tasks, POST /tasks, PUT /tasks/{taskNum}, DELETE /tasks/{taskNum}, GET /tasks/priority-weights, PUT /tasks/priority-weights |
| 应用场景 | 4 | GET/POST/PUT/DELETE /tasks/{taskNum}/applications[/{id}] |
| 工具 | 1 | GET /utils/fetch-title?url=... |
数据库(10 个核心表)
users, tasks, study_sessions, study_reports, study_report_fragments, study_expectations, task_applications, review_standard_mind_maps, review_recall_records, user_priority_weights
关键机制
- 多租户隔离:
TenantLineInnerInterceptor自动注入WHERE created_by = #{当前用户},排除user/flyway_schema_history表。 - 自动填充:
MetaObjectHandler自动填充created_by/updated_by/created_time/updated_time。 - 认证鉴权:Sa-Token 拦截
/**排除/login,Cookiesatoken,支持@SaCheckPermission注解式权限。 - 响应格式:
CommonResult<T>统一包装{ code, message, data }。 - CORS:可配置,local profile 允许所有来源。
响应规范
- 成功:
CommonResult.success(data),code=200。 - 业务错误:
CommonResult.error(msg),code=400,HTTP 200。 - 未登录:
GlobalExceptionHandler.handleNotLogin(),HTTP 401 + code=401。 - 参数校验失败:
MethodArgumentNotValidException,code=400。 - 用户可见错误文案必须口语化、可理解,避免“无法生成”“不存在”等技术化表述;技术细节写入日志。例如无学习报告时应提示“这个任务还没开始学习哦,学习后产生学习报告后再来吧”,而不是“没有学习报告,无法生成思维导图”。
DTO 转换
- MapStruct 编译期生成
*ConvertImpl.java,同名属性自动映射。 - 默认
unmappedTargetPolicy = IGNORE。 - 自定义映射使用
@Mapping(source, target)。 - 增删 DTO 字段后必须重新编译,否则生成代码不含新字段。
CORS
- 由
CorsProperties读取各 profile 的cors.allowed-origins。 allowed-origins: "*"时自动切换为allowedOriginPatterns("*"),兼容allowCredentials。
标题抓取
TitleFetcher:静态工具类,支持 HTTP→HTTPS 重定向和宽松 SSL。UtilsController:GET /utils/fetch-title?url=...代理端点。
运行环境
- 默认 profile:local(
application.yml中spring.profiles.active: local)。 - 编译命令:
mvn clean compile -DskipTests,需要 JDK 17。
配置文件
| Profile | 文件 |
|---|---|
| local | application-local.yml |
| dev | application-dev.yml |
| uat | application-uat.yml |
| prod | application-prod.yml |
| 公共 | application.yml |
AI 服务依赖
- 配置:
lpt.ai-service.url=http://localhost:5199 - 超时:600s
- AI 服务不可用时自动降级到内置规则引擎(
BuiltinMindMapGenerator)
启动命令
mvn clean compile -DskipTests # 编译(需要 JDK 17)
mvn spring-boot:run # 启动(默认 profile: local)
关联项目
| 项目 | 路径 | 端口 | 说明 |
|---|---|---|---|
| lpt-fe | ../lpt-fe/ |
5158 | Vue 3 前端,通过 /api 代理调用本服务 |
| lpt-ai | ../lpt-ai/ |
5199 | AI 服务,本服务通过 HTTP 调用其异步任务接口 |
项目规范
数据库迁移(Flyway Migration)
命名规则
- 脚本格式:
V{YYYYMMDD}_{序号}__{描述}.sql - 日期必须使用实际编写日期,不得使用过去的日期
- 序号从 1 开始,同一天多个脚本递增
- 描述使用下划线分隔的英文短语
核心原则
- 不可变性:已执行的迁移脚本永远不得修改
- 只增不减:数据库变更只能通过新增迁移脚本实现
- 向后兼容:新脚本应兼容已有数据
操作规范
- 删除表:创建新迁移脚本,使用
DROP TABLE IF EXISTS - 修改表结构:使用
ALTER TABLE语句 - 新增表:创建新迁移脚本,使用
CREATE TABLE
框架机制
行级数据隔离(多租户拦截器)
- 配置类:
MybatisPlusConfig注册TenantLineInnerInterceptor - 租户字段:
created_by(每个业务表的创建人字段) - 租户值来源:
StpUtil.getLoginIdAsString()(当前登录用户) - 自动注入: 所有 SELECT/UPDATE/DELETE 语句自动追加
WHERE created_by = #{当前用户} - 归属校验: 查询单条记录时拦截器自动校验
created_by,非本人数据直接返回空 - 排除表:
user、flyway_schema_history、databasechangelog、databasechangeloglock
自动填充(MetaObjectHandler)
- created_by / updated_by: 插入/更新时自动填充为当前登录用户
- created_time / updated_time: 插入/更新时自动填充当前时间
认证鉴权(Sa-Token)
- 会话管理: 基于
StpUtil的登录/登出/会话查询 - 权限校验:
@SaCheckPermission注解式权限控制 - 未登录处理: 全局异常处理器捕获
NotLoginException返回 401
编码规范
数据访问层
- 优先使用纯 MyBatis-Plus Java API(
Wrappers.<T>lambdaQuery()、selectList、selectById等),避免手写 XML SQL - 复杂查询通过
Wrappers链式构建条件,必要时使用.apply()拼接原生 SQL 片段