用途
本技能用于开发、审查和重构 Spring Boot 后端代码,并给出一套面向 youlai-boot 项目的具体工程约定。目标是交付符合现有项目架构、接口契约和质量要求的 Spring Boot 代码。其工作方式是先识别当前仓库的真实约定,再决定是沿用、渐进迁移还是明确重构,不把示例或偏好当成用户未要求的全局改造。
适用边界
在 youlai-boot 中使用本文件的项目约定。在其他 Spring Boot 项目中,只采用通用原则;目录、命名、响应包装和权限表达式以目标仓库为准。用户指令优先。修改前检查 AGENTS.md、构建文件、相关模块及未提交改动,避免覆盖用户工作。普通功能开发不自动扩大为安全审计、全仓重命名、框架升级或多模块拆分。
项目基线
资料列出如下基线:JDK 为 Java 17+;基础框架为 Spring Boot 4.x;ORM 为 MyBatis-Plus;数据库为 MySQL 8.x;缓存为 Redis 7.x;认证为 Spring Security + JWT / Redis Token;API 文档为 Springdoc OpenAPI + Knife4j;对象映射为 MapStruct,复杂联表可由 Mapper 直接投影 VO。并注明以目标仓库的 pom.xml 和配置类为最终事实;升级依赖或改变兼容基线前先验证官方兼容性。
架构边界
目标结构采用“业务域分包、域内分层”的单体架构,顶层包含:common(纯共享类型:基础对象、结果、常量、通用异常)、framework(Web、Security、MyBatis、缓存、切面等基础设施)、config(应用装配,不承载业务规则)、support(file、mail、sms、sse 等外部能力)、auth(认证业务)、system(用户、角色、菜单、部门、字典等)、form(动态表单)、workflow(工作流)、codegen(代码生成)。迁移期间可暂存 module/form、module/workflow,但新增代码不要继续制造两套顶级目录语言。
遵守的边界包括:common 不依赖 framework、config 或任何业务域;framework 不依赖具体业务域,通过 Port 或回调接口获取业务能力;config 可以作为组合根装配 framework、auth、system 等 Bean;跨业务域调用使用意图明确的 Facade、Port 或 Command,不传递另一个域的 Entity;业务 Service 接口不继承 MyBatis-Plus IService<Entity>,实现类可内部复用 ServiceImpl;避免双向包依赖;单体项目先用包边界和 ArchUnit 固化依赖方向,没有独立部署需求时不主动拆微服务。
配置类与属性类的归属判定:@Configuration 装配类看 Bean 消费方,仅被单个业务域或 support 组件消费的 Bean,装配类随域放置(如 auth/config/CaptchaConfig、support/mail/MailConfig);跨域或框架级 Bean 才留在全局 config/。@ConfigurationProperties 属性类看包根形态:根上已有兄弟类的包贴根平铺;根下只有子目录的集合根建 property/ 子包。属性类只挂 @ConfigurationProperties,不叠加 @Configuration,注册统一交给 @ConfigurationPropertiesScan。
模型职责与改进方向
资料给出模型类型的建议定义与改进重点:Entity 仅持久化层使用;Form 作为写请求输入;Query 作为查询条件,分页类使用 XxxPageQuery;VO 用于对外响应或只读投影;DTO 用于模块内部或模块间传输。新代码按规则收敛,历史代码除非用户要求不做无收益的批量重命名,包括:Entity 使用领域名(如 User、Role),表前缀由 @TableName("sys_user") 表达,保留现有 SysUser、SysLog 作为迁移兼容项;写模型使用 XxxForm,创建与更新字段或校验不同时拆为 XxxCreateForm、XxxUpdateForm;Path 中已有资源 ID 时以 Path 为唯一事实源,Form 不重复携带 ID;分页查询使用 XxxPageQuery,非分页过滤使用 XxxQuery,时间范围优先使用 createdFrom、createdTo 等明确的时间类型;不把权限范围、当前用户或租户等执行上下文塞进外部 Query;VO 只用于输出,不复用为写模型,Mapper 可为复杂联表直接返回 VO,但不接收 Controller Form;DTO 必须具有明确的内部传输语义;auth 模块与其他业务域统一采用 Form/Query/VO,不再并存 req/resp 两套后缀。
输入校验
@RequestBody 输入使用 @Valid;Controller 类需要校验 Path/Query 标量时使用 @Validated。分页参数约束 pageNum >= 1,并为 pageSize 设置合理上限。排序字段必须映射到服务端白名单;排序方向使用枚举或明确的允许值,禁止直接拼接任意 SQL 字段。状态、类型等有限集合优先使用枚举;为兼容数据库整数时,在边界完成转换和校验。动态表单的 Map<String, Object> 无法只靠 Bean Validation 覆盖,必须执行字段白名单、类型、长度和业务规则校验。不要只在新增接口校验;更新、状态变更、密码重置等写入口同样必须校验。
API 与响应
资源路径使用复数名词,如 /api/v1/users;动作端点只在无法自然表达为资源状态时使用。Controller 返回 Result<T> 或 PageResult<T>;无响应数据使用 Result<Void>,避免 Result<?>。Controller 负责协议适配,Service 不返回 Result,Mapper 不返回 Result 或 PageResult。现有模块可暂时让 Service 返回 IPage<VO>、Controller 调用 PageResult.success(page);同一模块不要混用 Page、IPage、PageResult 三种服务契约。新增成功优先返回资源 ID;更新、删除成功返回 Result<Void>。业务码保留现有 A****、B****、C**** 体系,同时使用合适的 HTTP 状态表达协议错误,如 400、401、403、404、409、429、500。新增/更新接口按实际幂等风险使用 @RepeatSubmit;增删改和关键动作按审计需要添加 @Log,不要机械标注所有查询。
持久化与对象转换
Entity 不直接从 Controller 返回,也不作为跨模块契约。单表简单映射优先 MapStruct;复杂联表查询允许 Mapper 直接投影 VO。禁止用 BeanUtils.copyProperties 或 JSON 序列化做常规对象转换;少量明确字段手写映射可接受。Entity 的主键策略和逻辑删除方式以项目全局 MyBatis-Plus 配置为准,不要同时编造一套冲突的 @TableLogic 或 ID 策略。
实施流程
阅读目标模块、相邻模块、数据库映射、配置和测试,确认真实契约;判断改动属于输入 Form、查询 Query、输出 VO、内部 DTO/Event/Context 中的哪一类;先定义校验、授权、事务边界和失败语义,再实现 Mapper、Service、Controller;检查跨域依赖,若需要另一个域的数据或动作,调用窄接口,不依赖其 Entity 或通用 IService;编译并运行与改动相关的测试,外部数据库、Redis 或第三方服务不可用时明确说明未验证部分;只修改任务范围内文件,报告兼容性影响和剩余迁移项。
注释原则
注释解释约束、原因、副作用、线程/事务要求和容易踩坑的行为,不重复类名、注解或代码表面含义。公共扩展点、跨模块接口和存在非显然约束的方法应写 Javadoc;简单内部 POJO、显而易见的 getter/setter 不强制逐项注释。需要稳定生成 Javadoc 摘要时优先使用 {@summary ...}。@author 沿用项目既有的作者约定;@since 写项目当前版本号,与 pom.xml 的 version 一致,升版本时同步更新,不写日期。API 字段优先由 @Schema 描述协议含义;Javadoc 补充领域约束,避免两处复制同一句话。代码变化时同步更新注释。
按需读取参考
认证、白名单、Token 或权限读 references/authentication.md;事务边界或事务失效读 references/transaction.md;MapStruct 或查询投影读 references/mapstruct.md;日志级别、异常日志、脱敏读 references/logging.md;新增业务资源或模块读 references/new-module.md;注释或 Javadoc 专项整理读 references/comments.md。
限制
资料未提供安装命令、代码示例的具体运行步骤、收费信息、支持的平台范围或具体效果数据。该技能面向 youlai-boot 项目约定,用于其他 Spring Boot 项目时仅适用通用原则。