trae solo模式规则和技能-项目规则示例
版本: 4.1 | 更新: 2026-01-21。
Java/Spring Boot 编码规范
版本: 4.1 | 更新: 2026-01-21
命名约定
类命名
| 类型 | 规则 | 示例 |
|---|---|---|
| 实体类 | 驼峰命名 | PromotionPlan |
| Controller | *Controller |
ProductController |
| Service 接口 | I*Service |
IProductService |
| Service 实现 | *ServiceImpl |
ProductServiceImpl |
| Mapper | *Mapper |
ProductMapper |
| DTO | *DTO |
ProductDTO |
| 请求对象 | *Req |
ProductPageReq |
| 响应对象 | *Rsp |
ProductDetailRsp |
| 枚举类 | *Enum |
OrderStatusEnum |
变量命名
| 类型 | 规则 | 示例 |
|---|---|---|
| 方法/字段 | lowerCamelCase |
getUserById |
| 常量 | UPPER_SNAKE_CASE |
MAX_BATCH_SIZE = 1000 |
| 数据库表 | lower_snake_case |
promotion_plan |
| 接口路径 | kebab-case |
/product-catalog/page |
Import 规则
- ❌ 禁止使用全限定类名,必须先 import 后使用简单类名
- ✅ 静态成员使用
import static
import static com.dsl.selection.component.constant.Constant.MAX_BATCH_SIZE;
import static com.dsl.base.exception.util.ServiceExceptionUtil.exception;
依赖注入
- ✅ 新代码使用
@RequiredArgsConstructor+private final构造器注入 - ❌ 新代码禁止
@Autowired字段注入 - ⚠️ 存量代码不强制要求修改
// ✅ 正确(使用 Lombok)
@Service
@RequiredArgsConstructor
public class ProductService {
private final ProductMapper productMapper;
}
// ❌ 错误
@Service
public class ProductService {
@Autowired
private ProductMapper productMapper;
}
日志规范
基本要求
- 使用
@Slf4j注解 - 使用占位符
{},❌ 禁止字符串拼接 - 业务名称用中括号标识:
[业务名称] - 敏感信息必须脱敏(手机号、身份证、密码、Token)
必须打印的节点
- 业务方法入口(打印参数)
- 数据库查询结果(特别是查询为空时)
- 调用外部系统前后(Feign、HTTP、MQ)
- 数据库写操作(插入、更新、删除)
- 异常情况(ERROR 级别,必须包含堆栈)
日志格式
// ✅ 正确
log.info("[促销目录生成],生成数据,计划ID: {},分区数量: {}", planId, zoneCount);
// ❌ 错误:字符串拼接
log.info("[促销目录生成],计划ID: " + planId);
// ❌ 错误:没有业务标识
log.info("生成数据,计划ID: {}", planId);
日志级别
INFO:关键业务流程WARN:警告信息(不影响业务)ERROR:错误异常(必须包含堆栈log.error("xxx", e))DEBUG:详细调试信息
异常处理
使用 ServiceExceptionUtil 抛出业务异常:
import static com.dsl.base.exception.util.ServiceExceptionUtil.exception;
import static com.dsl.base.exception.util.ServiceExceptionUtil.exception0;
// 方式一:自定义错误码(推荐)
if (record == null) {
throw exception(EXPORT_RECORD_NOT_EXISTS);
}
// 方式二:全局错误码 + 自定义消息
if (config == null) {
throw exception0(GlobalErrorCodeConstants.BAD_REQUEST.getCode(), "配置不存在");
}
❌ 禁止直接 throw new RuntimeException()
Controller 层规范
HTTP 方法约定
| 场景 | 方法 | 示例 |
|---|---|---|
| 单个资源查询 | GET | GET /product/{id} |
| 列表/条件查询 | POST | POST /product/list |
| 新增 | POST | POST /product/add |
| 修改 | POST | POST /product/update |
| 删除 | POST | POST /product/delete |
职责单一
Controller 只负责:接收参数、调用 Service、返回结果。
❌ 禁止在 Controller 写业务逻辑(查询数据库、条件判断、数据处理等)。
返回类型
统一使用 CommonResult<T>:
public CommonResult<ProductDetailRsp> getDetail(@Valid @RequestBody ProductDetailReq req)
public CommonResult<List<StoreItemDTO>> listStoreItems(@Valid @RequestBody QueryItemReq req)
public CommonResult<IPage<ProductPageDTO>> getPage(@Valid @RequestBody ProductPageReq req)
public CommonResult<Void> submitForApproval(@Valid @RequestBody SubmitApprovalReq req)
参数校验
- Controller 类添加
@Validated - 方法参数使用
@Valid @RequestBody - Req 对象字段使用校验注解
@Data
public class ProductAddReq {
@NotBlank(message = "商品编码不能为空")
private String itemCode;
@NotNull(message = "商品价格不能为空")
@DecimalMin(value = "0.01", message = "商品价格必须大于0")
private BigDecimal price;
}
嵌套对象校验
嵌套对象需要加 @Valid 才能触发内部校验:
@NotNull(message = "用户信息不能为空")
@Valid // 必须加
private UserInfo userInfo;
Service 层
复杂度控制
- ✅ 使用卫语句代替多层 if-else 嵌套
- 方法长度不超过 50 行
- if-else 嵌套不超过 2 层
- 超过 3 个分支考虑策略模式
// ❌ 错误:多层嵌套
if (order != null) {
if (order.getStatus() == 1) {
if (order.getAmount() > 0) {
// 业务逻辑
}
}
}
// ✅ 正确:卫语句
if (order == null) {
throw exception(ORDER_NOT_EXISTS);
}
if (order.getStatus() != 1) {
throw exception(INVALID_STATUS);
}
processPayment(order);
幂等性设计
写接口必须保证幂等,防止重复提交导致数据异常。
| 方案 | 适用场景 | 说明 |
|---|---|---|
| 唯一索引 | 防止重复插入 | 数据库层面保证 |
| Token 机制 | 表单重复提交 | 提交前获取 token,使用后失效 |
| 状态机 | 状态流转操作 | 只允许特定状态转换 |
| 业务单号去重 | 支付、扣款等 | 基于 orderNo 判断是否已处理 |
并发控制
乐观锁(推荐)
适用于冲突较少的场景:
// Entity 增加版本号
@Version
private Integer version;
更新时检查版本号,失败则抛出异常或重试。
分布式锁
使用 Redisson RLock:
- 设置合理的等待时间和锁超时时间
- 在 finally 中释放锁
- 只释放自己持有的锁
lock.isHeldByCurrentThread()
缓存规范
Key 命名
格式:{业务}:{模块}:{标识}
String key = "promotion:plan:" + planId;
String key = "user:info:" + userId;
TTL 设置
| 数据类型 | TTL | 说明 |
|---|---|---|
| 热点数据 | 1-5 分钟 | 高频访问 |
| 普通数据 | 30 分钟 | 一般业务数据 |
| 配置数据 | 1 小时 | 变更少 |
| 永不过期 | ❌ 禁止 | 必须设置 TTL |
缓存穿透防护
空值也缓存(短 TTL 如 5 分钟),防止缓存穿透。
缓存更新策略
先更新数据库,再删除缓存。
对象转换
- ❌ 禁止直接返回 Entity,必须转换为 DTO/Rsp
- 使用
BeanUtils.copyProperties(source, target)或 MapStruct - 注意:
BeanUtils.copyProperties是浅拷贝,嵌套对象需手动处理
配置安全
以下配置 ❌ 禁止写在代码或本地配置文件:
- 数据库密码
- Redis 密码
- 第三方 API Key / Secret
- JWT 密钥
- 加密盐值
✅ 敏感配置存储在 Nacos 配置中心,按环境隔离。
❌ 禁止在日志中打印敏感配置。
Mapper 层规范
- 简单查询使用 MyBatis Plus Lambda API
- 复杂查询使用 MyBatis XML
- ✅ 使用
#{}预编译参数,防止 SQL 注入 - ❌ 禁止使用
${}直接拼接 - 动态排序使用
<choose>白名单,不直接拼接字段名
<!-- ✅ 动态排序安全写法 -->
ORDER BY
<choose>
<when test="orderColumn == 'create_time'">create_time</when>
<when test="orderColumn == 'update_time'">update_time</when>
<otherwise>id</otherwise>
</choose>
数据库表设计规范
基础字段要求
实体类继承 BaseDO 时,建表语句必须包含以下基础字段:
| 字段名 | 类型 | 说明 | 必须 |
|---|---|---|---|
id |
bigint |
主键,自增 | ✅ |
create_time |
datetime |
创建时间 | ✅ |
update_time |
datetime |
更新时间 | ✅ |
creator |
varchar(64) |
创建者 | ✅ |
updater |
varchar(64) |
更新者 | ✅ |
deleted |
bit(1) |
逻辑删除标记 | ✅ |
建表语句模板
CREATE TABLE `table_name` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
-- 业务字段...
`creator` varchar(64) DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='表注释';
实体类继承
// ✅ 正确:继承 BaseDO,自动拥有基础字段
@Data
@TableName("promotion_plan")
@EqualsAndHashCode(callSuper = true)
public class PromotionPlan extends BaseDO {
@TableId(type = IdType.AUTO)
private Long id;
// 业务字段...
}
字段命名规范
| 规则 | 示例 |
|---|---|
表名、字段名使用 snake_case |
promotion_plan、create_time |
布尔字段使用 is_ 前缀或动词 |
is_active、deleted |
时间字段使用 _time 后缀 |
create_time、effect_time |
状态字段使用 status |
order_status、approval_status |
索引规范
| 类型 | 命名规则 | 示例 |
|---|---|---|
| 主键 | PRIMARY KEY |
PRIMARY KEY (id) |
| 唯一索引 | uk_表名_字段 |
uk_order_order_no |
| 普通索引 | idx_表名_字段 |
idx_order_user_id |
| 联合索引 | idx_表名_字段1_字段2 |
idx_order_user_id_status |
-- 索引示例
CREATE UNIQUE INDEX `uk_order_order_no` ON `order` (`order_no`);
CREATE INDEX `idx_order_user_id` ON `order` (`user_id`);
CREATE INDEX `idx_order_create_time` ON `order` (`create_time`);
批量处理
超过 1000 条记录必须分批处理:
int batchSize = 1000;
for (int i = 0; i < list.size(); i += batchSize) {
List<Entity> batch = list.subList(i, Math.min(i + batchSize, list.size()));
saveBatch(batch);
}
事务控制
基本规则
- 多表操作必须加
@Transactional(rollbackFor = Exception.class) - ⚠️ 事务方法必须是
public(private 不生效) - ⚠️ 避免同类方法内部调用(代理失效)
- 长事务拆分,避免锁表时间过长
多数据源事务限制
⚠️ 重要:@Transactional 只对主数据源生效,事务方法中 ❌ 禁止混用多个数据源。
// ❌ 错误:事务中混用 MySQL 和 Doris
@Transactional(rollbackFor = Exception.class)
public void syncData() {
// Doris 查询不在事务管理范围内
List<Data> dorisData = dorisMapper.selectList();
// MySQL 写入在事务中
mysqlMapper.saveBatch(dorisData);
}
// ✅ 正确:拆分方法,事务只包裹单数据源操作
public void syncData() {
// 1. 非事务方法查询 Doris
List<Data> dorisData = queryFromDoris();
// 2. 事务方法写入 MySQL
saveToMysql(dorisData);
}
@Transactional(rollbackFor = Exception.class)
public void saveToMysql(List<Data> data) {
mysqlMapper.saveBatch(data);
}
同类调用代理失效
// ❌ 同类调用事务不生效
public void methodA() {
this.methodB(); // methodB 的 @Transactional 不生效
}
// ✅ 正确:注入自身或拆分到另一个 Service
@Autowired
private ProductService self;
public void methodA() {
self.methodB(); // 通过代理调用,事务生效
}
空安全处理
// 集合判空
if (CollectionUtils.isEmpty(list)) {
return Collections.emptyList();
}
// 链式调用防空
String city = Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCity)
.orElse("");
接口文档(Apifox)
项目使用 Apifox IDEA 插件,通过 Javadoc 注释自动生成接口文档。
注释规范
/**
* 商品管理
*/
@RestController
public class ProductController {
/**
* 分页查询商品
* @param req 查询条件
* @return 商品分页列表
*/
@PostMapping("/page")
public CommonResult<IPage<ProductDTO>> getPage(@Valid @RequestBody ProductPageReq req) { }
}
字段注释
/**
* 商品名称(模糊匹配)
* @mock 阿莫西林
*/
private String name;
/**
* 状态:0-下架,1-上架
* @mock 1
*/
private Integer status;
特殊标签
| 标签 | 用途 |
|---|---|
@mock |
字段示例值 |
@ignore |
忽略该字段,不生成文档 |
异步处理
- 使用
@Async("线程池名")指定线程池 - ❌ 禁止使用默认 SimpleAsyncTaskExecutor
- ❌ 禁止在同类中调用
@Async方法(代理失效) - ❌ 禁止在
@Async方法中使用@Transactional(事务不生效)
异步方法需要返回值时使用 CompletableFuture<T>。
分布式事务(RocketMQ 事务消息)
项目使用 RocketMQ 事务消息实现最终一致性:
- 发送半消息(Half Message)→ MQ 暂存,不投递
- 执行本地事务
- 提交/回滚 → MQ 决定投递或丢弃
- 异常时 MQ 回查本地事务状态
关键点
- 使用
@RocketMQTransactionListener(txProducerGroup = "xxx")实现事务监听器 executeLocalTransaction:执行本地事务,返回 COMMIT/ROLLBACK/UNKNOWNcheckLocalTransaction:事务回查,必须实现幂等查询- 消费端也要做幂等(Redis 去重)
回查幂等
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
String bizId = (String) msg.getHeaders().get("bizId");
boolean exists = orderMapper.existsByBizId(bizId);
return exists ? COMMIT : ROLLBACK;
}
安全规范
XSS 防护
- 全局 XssFilter 过滤请求参数
- 富文本字段使用 Jsoup 白名单清洗
权限控制(可选)
项目主要通过 DmpSystemApi 查询用户区域权限实现权限控制。
@PreAuthorize 注解为可选方案,存量代码中有使用。
敏感操作审计
使用 AOP + @AuditLog 注解记录关键操作日志(删除、修改等)。
性能优化
N+1 查询
❌ 禁止循环查询数据库:
// ❌ 错误
for (Order order : orders) {
User user = userMapper.selectById(order.getUserId()); // N 次查询
}
// ✅ 正确:批量查询 + 内存关联
Set<Long> userIds = orders.stream().map(Order::getUserId).collect(Collectors.toSet());
Map<Long, User> userMap = userMapper.selectBatchIds(userIds).stream()
.collect(Collectors.toMap(User::getId, u -> u));
深度分页
❌ 深度分页禁止使用 OFFSET(性能差):
-- ❌ 错误
SELECT * FROM product LIMIT 100000, 10;
-- ✅ 正确:游标分页
SELECT * FROM product WHERE id > #{lastId} ORDER BY id LIMIT 10;
大数据量导出
使用流式查询 @Options(fetchSize = 1000) + 逐条写入,避免 OOM。
设计模式
| 模式 | 适用场景 | 说明 |
|---|---|---|
| 策略模式 | 多分支业务逻辑 | 如支付方式、导出格式 |
| 模板方法 | 流程固定、步骤可变 | 如导出流程 |
| 责任链 | 多级审批、多步校验 | 如审批流 |
测试规范
| 类型 | 命名 | 说明 | 是否必须 |
|---|---|---|---|
| Mock 测试 | *Test.java |
隔离外部依赖,纯逻辑测试 | 必须 |
| 集成测试 | *IT.java |
真实环境测试,需数据库 | 视环境 |
Mock 测试必须覆盖
- 正常流程(happy path)
- 边界条件(空值、临界值)
- 异常分支(参数错误、业务异常)
- 依赖返回异常
命名规范
格式:方法名_场景
void getById_success()
void getById_notFound()
void getById_nullId()
代码评审 Checklist
必查项
| 检查点 | 说明 |
|---|---|
| 命名规范 | 类名、方法名、变量名是否符合规范 |
| 日志规范 | 是否有业务标识,是否使用占位符 |
| 异常处理 | 是否使用统一异常,是否有兜底处理 |
| 参数校验 | Controller 是否有 @Valid,Service 是否有业务校验 |
| SQL 安全 | 是否使用 #{},是否有 SQL 注入风险 |
| 事务边界 | 多表操作是否有事务,是否混用数据源 |
| 空指针 | 是否有 NPE 风险,集合是否判空 |
| 幂等性 | 写接口是否保证幂等 |
性能检查
| 检查点 | 说明 |
|---|---|
| N+1 查询 | 是否有循环查询数据库 |
| 深度分页 | 是否使用游标分页 |
| 批量处理 | 超过 1000 条是否分批 |
更多推荐



所有评论(0)