Spring Boot 2.7.18 后端服务,MyBatis-Plus ORM,JWT 认证。
| Task | Location | Notes |
|---|---|---|
| REST API 端点 | src/main/java/com/etotem/cfc/controller/ |
按功能分组: admin/, auth/, assessment/, family/, guide/, task/, reward/ |
| 业务逻辑 | src/main/java/com/etotem/cfc/service/ |
Service 命名: XxxService.java |
| 数据实体 | src/main/java/com/etotem/cfc/entity/ |
使用 MyBatis-Plus 注解 |
| MyBatis Mapper | src/main/java/com/etotem/cfc/mapper/ |
接口文件,与XML映射对应 |
| SQL 映射文件 | src/main/resources/mapper/ |
MyBatis XML 文件 |
| 配置类 | src/main/java/com/etotem/cfc/config/ |
JWT, Security, Swagger, DatabaseInitializer |
| DTO传输对象 | src/main/java/com/etotem/cfc/dto/ |
请求/响应数据结构 |
| 数据迁移 | src/main/java/com/etotem/cfc/service/DataMigrationService.java |
sfms → cfc |
| Symbol | Type | Location | Role |
|---|---|---|---|
AuthController |
Controller | controller/auth/AuthController.java |
微信登录、JWT 认证 |
TaskService |
Service | service/TaskService.java |
任务业务逻辑核心 |
DanAssessmentController |
Controller | controller/DanAssessmentController.java |
DAN测评全链路(订单/预约/支付/结果) |
AssessmentAppointmentController |
Controller | controller/assessment/AssessmentAppointmentController.java |
测评预约管理 |
DataMigrationService |
Service | service/DataMigrationService.java |
sfms → cfc 全量数据迁移 |
User |
Entity | entity/User.java |
用户实体 (parent/child/teacher) |
Task |
Entity | entity/Task.java |
任务实体 |
DanAssessmentResult |
Entity | entity/DanAssessmentResult.java |
DAN测评结果(含孩子快照字段) |
DatabaseInitializer |
Config | config/DatabaseInitializer.java |
数据库迁移和初始化 |
SfmsDataSourceConfig |
Config | config/SfmsDataSourceConfig.java |
sfms 多数据源配置 |
@TableName、@TableId(type = IdType.AUTO)Result<T> 返回,包含 code/message/dataAuthorization: Bearer {token}Controller 结尾,Service 以 Service 结尾@Resource 代替 @Autowired,字段名必须与类型默认 Bean Name 一致(如 PaymentService 的字段名必须为 paymentService)@PostMapping(POST 方法),禁止使用 @GetMapping/@PutMapping/@DeleteMapping新增接口前: 必须运行 mvn clean compile 并启动项目验证无冲突;使用以下命令检查重复路由:
grep -rn '@GetMapping\|@PostMapping\|@PutMapping\|@DeleteMapping' src/main/java/com/etotem/cfc/controller/ | grep -oP '@\w+Mapping\("\K[^"]*' | sort -u
Bean名冲突检查: 新增 Controller/Service 时,确保类名不与其他包中的类重名(Spring 默认 Bean Name 为类名首字母小写)
application.yml@ts-ignore、as any 绕过类型检查@Resource(name="xxx") 与字段名不一致的注入方式,保持字段名与类型默认 Bean Name 一致@GetMapping/@PutMapping/@DeleteMapping — 统一使用 @PostMappingnew XxxMapper() — Mapper 必须通过 @Resource 注入awk '!seen[$0]++' 对 Java 源文件去重 — 会删除合法的重复行(如多个方法的 } 闭合括号)role 字段分流,家长端可切孩子端,切换过来的孩子端可退出切换,即时出需要密码。直接登录的孩子端不能切换到家长 端PointsServicespring.datasource.* + sfms 源库 sfms.datasource.*(只读)当出现 Unknown column 'xxx' in 'field list' 等字段不存在错误,或需要进行表结构变更时,按以下流程处理:
错误日志定位 → 查找实体类 → 检查 schema.sql → 添加迁移 → 同步 schema.sql → 编译验证
后端日志中出现类似以下错误:
Unknown column 'xxx' in 'field list'
Table 'xxx' doesn't exist
从错误信息中提取:表名、列名/对象名,并从异常堆栈找到触发点(哪个 Service/Controller)。
entity/ 目录找到对应实体类,确认字段已定义(@TableField 或成员变量)src/main/resources/schema.sql 中找到该表的 CREATE TABLE 语句,确认列是否已包含| 情况 | 修复方式 |
|---|---|
| schema.sql 建表语句有该列,但生产库没有(旧表) | 只需在 DatabaseInitializer.runMigrations() 添加 ALTER TABLE |
| schema.sql 没有该列,实体也没有 | 在实体添加字段 + schema.sql 建表语句补列 + DatabaseInitializer 加迁移 |
| 全新表 | schema.sql 添加 CREATE TABLE + DatabaseInitializer 的 runMigrations() 加迁移 |
| 仅调整约束/类型/默认值 | DatabaseInitializer.runMigrations() 加 MODIFY COLUMN |
DatabaseInitializer.java 的 runMigrations() 方法是所有 DDL 迁移的唯一入口。
ensureColumn(table, column, definition) 是已有的辅助方法(第 4099 行),自动处理重复列异常:
// 迁移N: xxx表添加yyy字段
ensureColumn("table_name", "column_name", "VARCHAR(50) COMMENT '字段说明'");
ensureColumn 不可用时(如需要 MODIFY / 多个列在同一个 try 块),使用标准模式:
// 迁移N: xxx表添加yyy字段(原因描述/需求编号)
try {
jdbcTemplate.execute("ALTER TABLE xxx ADD COLUMN yyy VARCHAR(50) COMMENT '字段说明'");
log.info("已添加yyy列到xxx表");
} catch (Exception e) {
// 列已存在,忽略错误
}
// 迁移N: 创建 xxx 表(功能描述)
try {
jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS xxx (" +
"id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
"...字段定义..." +
"INDEX idx_xxx (column)" +
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='表注释'");
log.info("已创建xxx表");
} catch (Exception e) {
// 表已存在,忽略错误
}
try {
jdbcTemplate.execute("ALTER TABLE xxx ADD INDEX idx_xxx (column)");
log.info("已添加idx_xxx索引到xxx表");
} catch (Exception e) {
// 索引已存在,忽略错误
}
try {
jdbcTemplate.execute("ALTER TABLE xxx MODIFY COLUMN yyy VARCHAR(100) COMMENT '新注释'");
log.info("已修改xxx.yyy字段");
} catch (Exception e) {
// 修改失败,忽略错误
}
schema.sql 中保持该表最新的完整定义:
schema.sql 对应表的 CREATE TABLE 语句中也加上该列定义(保持建表即包含所有列)schema.sql 追加该表的 CREATE TABLE IF NOT EXISTS 语句CREATE TABLE IF NOT EXISTS 创建的表:也追加到 schema.sql(保持 schema.sql 为完整定义快照)mvn clean compile # 编译验证通过即可
迁移代码是幂等的(try-catch 忽略已存在的列/表/索引),无需运行时验证。
迁移N,在文件末尾搜索 // 迁移 确认最新编号)// 迁移N: 表名 操作说明(原因/需求编号)log.info(),失败统一用空 catch 或 // 忽略ensureColumn() 添加列,它自动处理重复列异常;原始 try-catch 模式用于索引/表/非标准操作mvn clean compile # 编译验证(唯一验证方式)
mvn spring-boot:run # 启动开发服务器 (localhost:9082)
mvn test # 运行测试 (目前只有1个测试类)
cd cfc-langgraph && pip install -r requirements.txt && uvicorn src.app:app --port 9000 ```
mvn clean compile 验证编译通过192.168.16.251:3306/cfcapplication.ymlapplication.yml 的 sfms.datasource.*/api/migration/run