# LPT 后端服务(lpt-be) > Java Spring Boot 后端,提供 REST API、数据库访问、认证鉴权。 ## Git 提交规范 - 提交信息使用中文,简洁描述变更内容。 - 格式:`类型: 简述`,例如 `feat: 新增用户登录接口`、`fix: 修复多租户拦截器空指针`、`docs: 补充API文档`。 ## 技术栈 - 框架: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) ## 项目结构 ```text 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/ → 工具类 ``` ## 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`,Cookie `satoken`,支持 `@SaCheckPermission` 注解式权限。 - 响应格式:`CommonResult` 统一包装 `{ code, message, data }`。 - CORS:可配置,local profile 允许所有来源。 ## 配置文件 | 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`) ## 启动命令 ```bash 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.lambdaQuery()`、`selectList`、`selectById` 等),避免手写 XML SQL - 复杂查询通过 `Wrappers` 链式构建条件,必要时使用 `.apply()` 拼接原生 SQL 片段