6.3 KiB
6.3 KiB
编码风格规范
一、命名规范
| 类型 | 命名规则 | 示例 |
|---|---|---|
| Controller | {功能}RestController |
LotteryActivityRestController |
| Service 接口 | {功能}Service |
LotteryActivityRestService |
| Service 实现 | {功能}ServiceImpl |
LotteryActivityRestServiceImpl |
| 写操作执行器 | {功能}CmdExe 或 {功能}Exe |
LotteryDrawExe |
| 查询执行器 | {功能}QryExe |
LotteryRecordQryExe |
| 写命令 | {功能}Cmd |
LotteryDrawCmd |
| 查询命令 | {功能}QryCmd |
LotteryRecordQryCmd |
| 返回对象 | {功能}CO |
LotteryDrawResultCO |
| DAO | {实体名}DAO |
LotteryTicketDAO |
| Entity | {实体名} |
LotteryTicket |
| 数据库服务 | {功能}DatabaseService |
LotteryActivityDatabaseService |
| Gateway | {功能}Gateway + {功能}GatewayImpl |
LotteryActivityGateway |
二、Controller 规范
/**
* 功能说明.
*
* @author xxx
* @eo.api-type http
* @eo.groupName 模块名.子模块名
* @eo.path /模块/资源
*/
@RestController
@RequestMapping(value = "/user/user-profile", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class UserProfileRestController extends BaseController {
private final UserProfileService userProfileService;
/**
* 接口说明.
*
* @eo.name 接口名称
* @eo.url /具体路径(GET 无路径时留空)
* @eo.method get/post/put/delete
* @eo.request-type formdata(GET)/ json(POST/PUT)
*/
@GetMapping
public UserProfileDTO getProfile(UserProfileQryCmd cmd) {
return userProfileService.getUserProfile(cmd);
}
@PostMapping("/draw")
public LotteryDrawResultCO draw(@RequestBody @Validated LotteryDrawCmd cmd) {
return lotteryService.draw(cmd);
}
}
关键点:
- 继承
BaseController @RequiredArgsConstructor(构造器注入)- API 文档用
@eo.注解,不用 Swagger - GET 请求参数直接用 Cmd 对象接收(无
@RequestBody) - POST/PUT 用
@RequestBody @Validated
三、Cmd / CO 规范
// 写命令 - 继承 AppExtCommand(包含 reqUserId 等公共字段)
@Data
public class LotteryDrawCmd extends AppExtCommand {
@NotNull
private Long activityId;
@Min(1) @Max(10)
private Integer drawCount;
}
// 查询命令 - 分页继承 PageQueryCmd
@Data
public class LotteryRecordQryCmd extends PageQueryCmd {
private Long activityId;
}
// 返回对象
@Data
public class LotteryDrawResultCO {
private Long prizeId;
private String prizeName;
}
规则:
- 校验注解用
jakarta.validation.constraints.*(不用 javax) - Cmd 需要用户身份时继承
AppExtCommand,通过cmd.getReqUserId()获取当前用户
四、Service / CmdExe 规范
// ServiceImpl - 门面,调用 CmdExe
@Service
@RequiredArgsConstructor
@Slf4j
public class LotteryActivityRestServiceImpl implements LotteryActivityRestService {
private final LotteryDrawExe lotteryDrawExe;
private final LotteryRecordQryExe recordQryExe;
@Override
public LotteryDrawResultCO draw(LotteryDrawCmd cmd) {
return lotteryDrawExe.execute(cmd);
}
}
// CmdExe - 核心业务逻辑
@Component
@RequiredArgsConstructor
@Slf4j
public class LotteryDrawExe {
private final LotteryActivityDatabaseService lotteryDbService;
@Transactional
public LotteryDrawResultCO execute(LotteryDrawCmd cmd) {
// 1. 参数校验
// 2. 业务逻辑
// 3. 记录日志
log.info("用户抽奖: userId={}, activityId={}", cmd.getReqUserId(), cmd.getActivityId());
// 4. 返回结果
}
}
五、Infrastructure 规范
// DAO - 继承 BaseDAO
public interface LotteryTicketDAO extends BaseDAO<LotteryTicket> {}
// DatabaseService - 简单场景直接用
@Service
@RequiredArgsConstructor
public class LotteryActivityDatabaseService {
private final LotteryTicketDAO ticketDAO;
public void consumeTicket(Long userId, Long activityId) {
LambdaQueryWrapper<LotteryTicket> wrapper = new LambdaQueryWrapper<LotteryTicket>()
.eq(Objects.nonNull(userId), LotteryTicket::getUserId, userId)
.eq(Objects.nonNull(activityId), LotteryTicket::getActivityId, activityId);
// ...
}
}
// Gateway - 复杂场景:锁 + 缓存 + 多数据源
@Component
@RequiredArgsConstructor
public class LotteryActivityGatewayImpl implements LotteryActivityGateway {
private final LotteryTicketDAO ticketDAO;
private final RedisTemplate<String, Object> redisTemplate;
@Override
public void consumeTicketWithLock(Long userId, Long activityId) {
String lockKey = "lottery:lock:" + userId;
// 分布式锁 + DB 操作 + 缓存更新
}
}
六、通用代码规范
条件判断
// ✅
if (StringUtils.isNotBlank(name)) { ... }
if (Objects.nonNull(userId)) { ... }
// ❌
if (name != null && !name.isEmpty()) { ... }
if (userId != null) { ... }
金额
// ✅
BigDecimal amount = new BigDecimal("100.00");
BigDecimal total = a.add(b);
// ❌ 禁止
double amount = 100.00;
返回分页
return PageResult.of(records, total, cmd.getPageNum(), cmd.getPageSize());
异常
// ✅
throw new BusinessException("抽奖券不足");
// ❌
throw new RuntimeException("抽奖券不足");
Redis Key 规范
缓存: {module}:{entity}:{id} user:info:10001
排行榜: ranking:{type}:{period}:{date} ranking:send_gift:day:20240101
分布式锁: {module}:lock:{bizId} coin:lock:10001
七、新功能开发顺序(黄金路径)
- 定义 Cmd / CO(other-client)
- 定义 Service 接口(other-client)
- 实现 CmdExe(other-application)
- 实现 ServiceImpl(other-application)
- 创建 Controller(other-adapter)
- 按需创建 DatabaseService 或 Gateway(other-infrastructure)
- 如需跨服务调用,添加 Inner API
八、质量检查清单
- 命名清晰,无 a/b/temp 类命名
- 参数校验(
@Validated、@NotNull) - 写操作有
@Transactional - 金额操作有幂等性保障(bizNo)
- 并发场景有分布式锁
- 关键操作有
log.info/log.error - 业务异常用
BusinessException - 无魔法值(常量或枚举)
- 分页查询用
PageResult