AI学习 Java后端编码规范
更新时间:2026-03-10
结论:这个仓库的 Java 后端开发已经形成了比较明确的固定套路。下次继续写后端代码时,默认按“模块化目录 + DTO 入出参 +
R<T>统一返回 + Service 承载业务 + MyBatis-Flex 承载单表 ORM + XML 承载复杂 SQL +BusinessException承载业务异常”的方式执行。
1. 当前项目的总规则
1.1 根包名
- 根包名统一为:
com.fuyo.dic
1.2 模块化组织
系统按模块拆分,当前典型模块有:
fuyo-commonfuyo-frameworkfuyo-ccc-bosfuyo-launch
业务代码主要集中在 fuyo-common。
1.3 每个业务模块的标准目录
由代码生成器和当前工程实践共同决定,标准目录基本如下:
com.fuyo.dic.{module}/
├── controller/
├── entity/
│ └── table/
├── mapper/
├── service/
│ └── impl/
├── dto/
│ ├── req/
│ └── resp/
└── enums/
结论:
- 新模块优先沿用这套目录,不要随意发明新层次
dto/req和dto/resp是项目当前明确在用的结构,不要省略
2. 资源文件规范
Mapper.xml统一放在resources/mapper/- 命名规则统一是:
XxxMapper.xml
当前例子:
fuyo-common/src/main/resources/mapper/SysUserMapper.xmlfuyo-common/src/main/resources/mapper/SysRoleMapper.xml
结论:
- Mapper 接口在
java/.../mapper - SQL 文件在
resources/mapper - 不要把 XML 混进
java目录
3. Controller 规范
3.1 基本形态
当前项目里的标准 Controller 写法大致如下:
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(UrlConfig.API_SYSTEM_MENU)
public class MenuController {
private final SysMenuService sysMenuService;
@SaCheckLogin
@GetMapping
public R<List<MenuPageResp.MenuItem>> list(MenuPageReq req) {
log.info("获取菜单搜索列表:req={}", req);
return R.ok(sysMenuService.list(req));
}
}
3.2 必备注解
默认优先使用:
@Slf4j@RestController@RequiredArgsConstructor@RequestMapping@GetMapping / @PostMapping / @PutMapping / @DeleteMapping
3.3 登录校验
项目规范是:
- 受保护接口默认加
@SaCheckLogin - 认证类开放接口例外,例如验证码、登录接口
真实例子:
AuthController.getCaptcha()没有@SaCheckLoginAuthController.login()没有@SaCheckLogin- 其他受保护接口普遍有
@SaCheckLogin
结论:
- 不要机械地给所有接口都加
@SaCheckLogin - 规则应该写成:默认需要登录校验,认证入口例外
3.4 控制器返回值
控制器层统一返回 R<T>。
当前项目实际用法:
- 返回数据:
R.ok(data) - 返回消息:
R.ok("操作成功") - 返回消息 + 数据:
R.ok("登录成功", data) - 返回失败:
R.error("操作失败")
示例:
public R<Object> add(@Valid @RequestBody AddMenuReq req) {
sysMenuService.add(req);
return R.ok("操作成功");
}
结论:
- Controller 不直接返回裸对象
- 删除、新增、修改这类无数据返回场景,统一用
R<Object>或R<String> - 如果不确定泛型,按项目约定可以使用
Object
3.5 路由定义方式
项目明确要求类级主路由写在 UrlConfig 中。
真实做法:
@RequestMapping(UrlConfig.API_SYSTEM_MENU)@GetMapping(UrlConfig.auth_captcha)这类认证接口也直接复用常量
结论:
- 不要在 Controller 里硬编码
/api/system/xxx - 先去
UrlConfig.java增加或复用路由常量
4. DTO 规范
4.1 请求 DTO
请求对象统一放 dto/req。
典型命名:
AddMenuReqUpdateMenuReqMenuPageReqLoginReq
4.2 响应 DTO
响应对象统一放 dto/resp。
典型命名:
MenuPageRespUserPageRespRolePageRespLoginResp
4.3 DTO 命名约定
默认使用:
- 新增:
AddXxxReq - 修改:
UpdateXxxReq - 分页/查询:
XxxPageReq - 列表/分页返回:
XxxPageResp - 特殊业务返回:
XxxResp
4.4 嵌套 DTO
当前项目已大量使用内部静态类承载子项:
MenuPageResp.MenuItemUserPageResp.UserItemUserPageResp.RoleInfo
结论:
- 如果响应结构天然是“列表主体 + 子项”,优先用内部静态类
- 不要随意把一个页面返回拆成过多零散类
5. 参数校验规范
5.1 控制器入参
Controller 层统一优先使用 @Valid。
例如:
public R<Object> add(@Valid @RequestBody AddMenuReq req)
5.2 DTO 字段校验
当前项目已实际使用:
@NotBlank@NotNull
例如:
@NotBlank(message = "用户名不能为空") private String username;
5.3 全局校验异常处理
项目已经有统一异常处理:
MethodArgumentNotValidExceptionBindException
位置:
fuyo-framework/src/main/java/com/fuyo/dic/framework/exception/GlobalExceptionHandler.java
结论:
- 参数校验失败会自动转成统一
R.error(400, message) - Controller 不要自己手写重复的参数错误处理
5.4 实际落地提醒
虽然规范要求明确,但当前代码里个别字段校验还不完整,比如有些 @NotNull 被注释掉了。
结论:
- 下次新写代码时按规范补齐校验
- 如果改旧代码,优先保持兼容,不要盲目一次性收紧所有老接口校验
6. Service 规范
6.1 Service 接口职责
Service 接口层只定义业务方法,不放实现。
当前典型形态:
public interface SysUserService extends IService<SysUser> {
UserPageResp page(UserPageReq req);
void add(AddUserReq req);
void update(UpdateUserReq req);
}
结论:
- 接口负责暴露业务能力
- 具体实现放到
service/impl
6.2 Service 实现层职责
ServiceImpl 承担:
- 业务规则校验
- 数据库操作
- 多表数据组装
- 事务控制
- 日志记录
当前典型注解组合:
@Slf4j@Service@RequiredArgsConstructor
6.3 事务规范
凡是数据库写操作,默认加:
@Transactional(rollbackFor = Exception.class)
适用场景:
- 新增
- 修改
- 删除
- 重置密码
- 多表关系维护
结论:
- 纯查询一般不加事务
- 只要跨多步写操作,默认上事务
6.4 ServiceImpl 内部的编码习惯
从当前代码看,默认模式是:
log.info打入口日志- 做业务校验
- 调 ORM / Mapper
- 失败抛
BusinessException - 成功打结果日志
例如:
SysUserServiceImplSysRoleServiceImplSysMenuServiceImpl
7. 数据访问规范
7.1 优先使用 MyBatis-Flex Service API
项目明确约定:
- 优先使用 MyBatis-Flex 提供的
ServiceImpl/IService能力 - 常规 CRUD、条件查询、分页查询,优先不要直接手写 Mapper 调用
本项目常用 API:
savesaveBatchgetByIdgetOnelistcountupdateByIdremovepage
7.2 QueryWrapper 的使用边界
适用场景:
- 单表查询
- 动态条件拼装
- 唯一性校验
- 逻辑删除过滤
7.3 XML SQL 的使用边界
复杂多表 Join 查询时,优先使用 Mapper XML。
真实例子:
SysUserMapper + SysUserMapper.xml
这类场景通常包括:
- 连表分页
- DTO 投影
- 批量附加关联信息
- 复杂字段格式化
结论:
- 不要为了追求“全用 Flex”而把复杂 SQL 写得很难维护
- 单表 Flex,复杂查询 XML,这就是本项目的真实规范
8. Mapper 规范
8.1 基本形式
@Mapper
public interface XxxMapper extends BaseMapper<XxxEntity> {
}
8.2 自定义方法
如果有复杂 SQL,可以在 Mapper 中声明方法,并在 XML 中实现。
例如:
selectUserPageListselectUserCountselectUserRolesList
8.3 参数传递
多参数或复杂参数时,使用 @Param。
结论:
- 简单 CRUD 靠
BaseMapper - 复杂查询通过 Mapper 自定义方法 + XML
9. 异常处理规范
9.1 业务异常
业务异常统一抛:
BusinessException
不要在 Service 里随便返回 "失败"、false 来表达业务错误。
典型写法:
if (existUser != null) {
throw new BusinessException("用户名已存在");
}
9.2 全局异常处理
项目已统一处理:
BusinessExceptionNotLoginExceptionNotPermissionExceptionNotRoleException- 参数校验异常
- 其他系统异常
结论:
- Controller 和 Service 不要重复 try-catch 这些常规业务异常
- 非特殊情况,抛出去交给全局异常处理器
10. 日志规范
当前项目主风格:
- Controller 和 ServiceImpl 普遍使用
@Slf4j - 方法入口打印关键参数
- 成功后打印关键结果
- 异常不在业务层重复吞掉
推荐写法:
log.info("添加用户:req={}", req);
log.info("添加用户成功:userId={}, username={}", user.getId(), user.getUsername());
结论:
- 日志重点放业务动作和关键主键
- 注意不要打印敏感信息,如明文密码
11. 实体类规范
当前实体的主流风格是:
@Data@Builder@NoArgsConstructor@AllArgsConstructor@Table("table_name")@Id(keyType = KeyType.Auto)@Serial
字段要求:
- 每个字段写中文注释
- 表字段与 Java 字段按当前项目约定映射
结论:
- 新实体优先沿用代码生成产物风格
- 不要随意切换成另一套实体编码风格
12. 命名规范
当前项目推荐命名:
- Controller:
XxxController - Service:
XxxService - ServiceImpl:
XxxServiceImpl - Mapper:
XxxMapper - Entity:
Xxx - Req DTO:
AddXxxReq/UpdateXxxReq/XxxPageReq - Resp DTO:
XxxResp/XxxPageResp
结论:
- 命名尽量贴业务语义
- 不要出现
TestController、TempService这类临时命名进入正式代码
13. 一个标准后端接口的开发顺序
下次新增一个业务接口,默认按这个顺序:
- 在
UrlConfig增加路由常量 - 新建或补充
dto/req与dto/resp - 在 Controller 中定义接口,返回
R<T> - Controller 上加
@SaCheckLogin,认证开放接口除外 - 入参加
@Valid - 在 Service 接口定义方法
- 在 ServiceImpl 实现业务逻辑
- 常规查询优先 MyBatis-Flex Service API
- 复杂 Join 查询补 Mapper XML
- 写操作方法加
@Transactional - 业务错误抛
BusinessException
14. 当前仓库下次直接复用的默认动作
如果下次让我继续写 Java 后端代码,我默认遵守这些动作:
- 路由先看
UrlConfig - 入参先建
dto/req - 出参先建
dto/resp - Controller 统一返回
R<T> - 默认加
@SaCheckLogin,登录/验证码等开放接口除外 - 默认加
@Valid - 业务逻辑写进 ServiceImpl
- 写操作默认加
@Transactional - ORM 优先走 MyBatis-Flex
- 多表复杂查询优先 XML
- 业务错误统一抛
BusinessException
15. 容易踩坑的地方
- 在 Controller 里直接写业务逻辑
- 路由写死字符串,不走
UrlConfig - 直接返回裸对象,不包
R<T> - 忘记给写操作加事务
- 忘记给受保护接口加
@SaCheckLogin - 登录/验证码接口误加
@SaCheckLogin - DTO 不分
req/resp,导致接口层混乱 - 能用 Service API 的地方反而直接乱调 Mapper
- 复杂 Join 还硬写在 QueryWrapper 里
- 业务异常不用
BusinessException
16. 一句话心智模型
这个项目的 Java 后端编码规范,本质上是在强调“分层清晰、边界明确、风格统一”:Controller 负责接入和返回,ServiceImpl 负责业务,MyBatis-Flex 负责常规 ORM,XML 负责复杂 SQL,
R<T>负责统一响应,BusinessException负责统一业务失败。