后端开发规范
1. 项目结构
1.1 整体架构
梵医云后端项目采用微服务架构,基于 Spring Boot 3.3.1 + Java 17 开发。
fanyi-cloud/
├── fanyi-dependencies/ # 依赖管理
├── fanyi-framework/ # 框架层
│ ├── fanyi-common/ # 公共模块
│ ├── fanyi-spring-boot-starter-web/ # Web启动器
│ ├── fanyi-spring-boot-starter-mybatis/ # MyBatis启动器
│ ├── fanyi-spring-boot-starter-security/ # 安全启动器
│ ├── fanyi-spring-boot-starter-redis/ # Redis启动器
│ └── ...
├── fanyi-gateway/ # 网关服务
├── fanyi-module-system/ # 系统模块
│ ├── fanyi-module-system-api/ # API接口定义
│ └── fanyi-module-system-biz/ # 业务实现
├── fanyi-module-infra/ # 基础设施模块
├── fanyi-module-mall/ # 商城模块
├── fanyi-module-crm/ # CRM模块
├── fanyi-module-erp/ # ERP模块
├── fanyi-module-bpm/ # 工作流模块
└── ...1.2 模块结构规范
每个业务模块采用统一的目录结构:
fanyi-module-{module}/
├── fanyi-module-{module}-api/ # API接口定义
│ └── src/main/java/com/fanyi/cloud/module/{module}/api/
│ ├── {domain}/dto/ # 数据传输对象
│ └── {domain}/ # API接口
└── fanyi-module-{module}-biz/ # 业务实现
└── src/main/java/com/fanyi/cloud/module/{module}/
├── controller/ # 控制器层
│ ├── admin/ # 管理后台接口
│ │ └── {domain}/
│ │ ├── vo/ # 视图对象
│ │ └── {Domain}Controller.java
│ └── app/ # 移动端接口
├── service/ # 服务层
│ └── {domain}/
│ ├── {Domain}Service.java
│ └── {Domain}ServiceImpl.java
├── dal/ # 数据访问层
│ ├── dataobject/ # 数据对象
│ │ └── {domain}/
│ │ └── {Domain}DO.java
│ └── mysql/ # Mapper接口
│ └── {domain}/
│ └── {Domain}Mapper.java
├── convert/ # 对象转换器
│ └── {domain}/
│ └── {Domain}Convert.java
├── framework/ # 框架配置
│ ├── config/ # 配置类
│ ├── security/ # 安全配置
│ └── mq/ # 消息队列
├── mq/ # 消息队列
│ └── producer/ # 消息生产者
├── job/ # 定时任务
│ └── demo/
└── {Module}ServerApplication.java # 启动类2. 命名规范
2.1 包命名规范
- 基础包名:
com.fanyi.cloud.module.{module} - controller包:
com.fanyi.cloud.module.{module}.controller - service包:
com.fanyi.cloud.module.{module}.service - dal包:
com.fanyi.cloud.module.{module}.dal - convert包:
com.fanyi.cloud.module.{module}.convert - framework包:
com.fanyi.cloud.module.{module}.framework
2.2 类命名规范
| 类型 | 命名规则 | 示例 |
|---|---|---|
| Controller | {Domain}Controller | UserController |
| Service | {Domain}Service | UserService |
| ServiceImpl | {Domain}ServiceImpl | UserServiceImpl |
| Mapper | {Domain}Mapper | UserMapper |
| DataObject | {Domain}DO | UserDO |
| VO (Request) | {Operation}{Domain}ReqVO | UserSaveReqVO |
| VO (Response) | {Domain}RespVO | UserRespVO |
| VO (Page) | {Domain}PageReqVO | UserPageReqVO |
| VO (Simple) | {Domain}SimpleRespVO | UserSimpleRespVO |
| Convert | {Domain}Convert | UserConvert |
| Enum | {Domain}Enum | SexEnum |
| Constants | {Domain}Constants | UserConstants |
2.3 变量命名规范
- 使用驼峰命名法
- 布尔类型变量以
is开头 - 集合类型变量使用复数形式
java
private String username;
private Boolean isAdmin;
private List<UserDO> users;
private Map<Long, String> userMap;2.4 方法命名规范
| 操作 | 命名规则 | 示例 |
|---|---|---|
| 新增 | create | createUser |
| 修改 | update | updateUser |
| 删除 | delete | deleteUser |
| 查询单个 | get | getUser |
| 查询列表 | list{Domain}s | listUsers |
| 查询分页 | get{Domain}Page | getUserPage |
| 统计 | count{Domain}s | countUsers |
| 校验 | validate | validateUser |
3. 代码分层规范
3.1 Controller层
Controller层负责接收HTTP请求,参数校验,调用Service层处理业务逻辑,返回响应结果。
java
@Tag(name = "管理后台 - 用户")
@RestController
@RequestMapping("/system/user")
@Validated
public class UserController {
@Resource
private AdminUserService userService;
@PostMapping("/create")
@Operation(summary = "新增用户")
@PreAuthorize("@ss.hasPermission('system:user:create')")
public CommonResult<Long> createUser(@Valid @RequestBody UserSaveReqVO reqVO) {
Long id = userService.createUser(reqVO);
return success(id);
}
@GetMapping("/page")
@Operation(summary = "获得用户分页列表")
@PreAuthorize("@ss.hasPermission('system:user:list')")
public CommonResult<PageResult<UserRespVO>> getUserPage(@Valid UserPageReqVO pageReqVO) {
PageResult<AdminUserDO> pageResult = userService.getUserPage(pageReqVO);
return success(pageResult);
}
}Controller层规范:
- 使用
@RestController注解 - 使用
@RequestMapping定义基础路径 - 使用
@Tag注解添加API文档说明 - 使用
@Operation注解添加接口说明 - 使用
@PreAuthorize注解进行权限控制 - 使用
@Valid或@Validated进行参数校验 - 返回统一响应类型
CommonResult - 不包含业务逻辑,只负责参数接收和响应返回
3.2 Service层
Service层负责业务逻辑处理,事务控制,调用Mapper层进行数据操作。
java
@Service("adminUserService")
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {
@Resource
private AdminUserMapper userMapper;
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}",
success = CREATE_SUCCESS)
public Long createUser(UserSaveReqVO createReqVO) {
validateUserExists(null, createReqVO.getUsername(),
createReqVO.getMobile(), createReqVO.getEmail());
AdminUserDO user = UserConvert.INSTANCE.convert(createReqVO);
user.setPassword(passwordEncoder.encode(user.getPassword()));
userMapper.insert(user);
return user.getId();
}
private void validateUserExists(Long id, String username, String mobile, String email) {
if (StrUtil.isNotEmpty(username)) {
AdminUserDO user = userMapper.selectByUsername(username);
if (user != null && !user.getId().equals(id)) {
throw exception(USER_USERNAME_EXISTS);
}
}
}
}Service层规范:
- 使用
@Service注解 - 实现对应的Service接口
- 使用
@Transactional注解控制事务 - 使用
@LogRecord注解记录操作日志 - 包含完整的业务逻辑
- 进行参数校验和业务规则校验
- 抛出业务异常使用
ServiceException - 使用
@Resource注入依赖
3.3 Mapper层
Mapper层负责数据库操作,继承 BaseMapperX 获得基础CRUD方法。
java
@Mapper
public interface AdminUserMapper extends BaseMapperX<AdminUserDO> {
default AdminUserDO selectByUsername(String username) {
return selectOne(AdminUserDO::getUsername, username);
}
default AdminUserDO selectByEmail(String email) {
return selectOne(AdminUserDO::getEmail, email);
}
default PageResult<AdminUserDO> selectPage(UserPageReqVO reqVO, Collection<Long> deptIds) {
return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
.likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
.likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
.eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
.inIfPresent(AdminUserDO::getDeptId, deptIds)
.orderByDesc(AdminUserDO::getId));
}
}Mapper层规范:
- 使用
@Mapper注解 - 继承
BaseMapperX<DO>获得基础方法 - 使用
LambdaQueryWrapperX构建查询条件 - 使用
selectOne、selectList、selectPage等方法 - 复杂查询使用自定义SQL方法
- 不包含业务逻辑,只负责数据访问
3.4 DataObject层
DataObject层对应数据库表,使用MyBatis-Plus注解映射。
java
@TableName(value = "system_users", autoResultMap = true)
@KeySequence("system_users_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AdminUserDO extends TenantBaseDO {
@TableId
private Long id;
private String username;
private String password;
private String nickname;
private String email;
private String mobile;
private Integer sex;
private String avatar;
private Integer status;
private String loginIp;
private LocalDateTime loginDate;
}DataObject层规范:
- 使用
@TableName注解指定表名 - 使用
@TableId注解标记主键 - 使用
@KeySequence注解指定序列(Oracle等) - 继承
TenantBaseDO获得租户字段 - 使用
@Data注解自动生成getter/setter - 使用
@Builder注解支持构建器模式 - 字段类型与数据库类型对应
- 不包含业务逻辑
3.5 Convert层
Convert层负责对象之间的转换,使用MapStruct自动生成转换代码。
java
@Mapper
public interface UserConvert {
UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);
default List<UserRespVO> convertList(List<AdminUserDO> list, Map<Long, DeptDO> deptMap) {
return CollectionUtils.convertList(list, user -> convert(user, deptMap.get(user.getDeptId())));
}
default UserRespVO convert(AdminUserDO user, DeptDO dept) {
UserRespVO userVO = BeanUtils.toBean(user, UserRespVO.class);
if (dept != null) {
userVO.setDeptName(dept.getName());
}
return userVO;
}
default AdminUserDO convert(UserSaveReqVO reqVO) {
return BeanUtils.toBean(reqVO, AdminUserDO.class);
}
}Convert层规范:
- 使用
@Mapper注解(MapStruct) - 定义
INSTANCE常量 - 使用
BeanUtils.toBean进行对象转换 - 处理复杂转换逻辑
- 不包含业务逻辑
4. 数据库操作规范
4.1 基础CRUD操作
使用 BaseMapperX 提供的基础方法:
java
// 插入
userMapper.insert(userDO);
// 根据ID查询
AdminUserDO user = userMapper.selectById(id);
// 根据条件查询单个
AdminUserDO user = userMapper.selectOne(AdminUserDO::getUsername, username);
// 根据条件查询列表
List<AdminUserDO> users = userMapper.selectList(AdminUserDO::getDeptId, deptId);
// 分页查询
PageResult<AdminUserDO> pageResult = userMapper.selectPage(reqVO, wrapper);
// 更新
userMapper.updateById(userDO);
// 删除
userMapper.deleteById(id);4.2 条件查询构建
使用 LambdaQueryWrapperX 构建查询条件:
java
new LambdaQueryWrapperX<AdminUserDO>()
.eq(AdminUserDO::getStatus, 1) // 等于
.ne(AdminUserDO::getDeleted, true) // 不等于
.like(AdminUserDO::getUsername, "admin") // 模糊查询
.likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile()) // 条件模糊查询
.in(AdminUserDO::getDeptId, deptIds) // IN查询
.between(AdminUserDO::getCreateTime, startTime, endTime) // BETWEEN查询
.gt(AdminUserDO::getAge, 18) // 大于
.ge(AdminUserDO::getAge, 18) // 大于等于
.lt(AdminUserDO::getAge, 60) // 小于
.le(AdminUserDO::getAge, 60) // 小于等于
.isNull(AdminUserDO::getDeletedTime) // IS NULL
.isNotNull(AdminUserDO::getUpdateTime) // IS NOT NULL
.orderByDesc(AdminUserDO::getId) // 降序排序
.orderByAsc(AdminUserDO::getCreateTime) // 升序排序4.3 分页查询
使用统一的分页查询方法:
java
default PageResult<AdminUserDO> selectPage(UserPageReqVO reqVO, Collection<Long> deptIds) {
return selectPage(reqVO, new LambdaQueryWrapperX<AdminUserDO>()
.likeIfPresent(AdminUserDO::getUsername, reqVO.getUsername())
.likeIfPresent(AdminUserDO::getMobile, reqVO.getMobile())
.eqIfPresent(AdminUserDO::getStatus, reqVO.getStatus())
.inIfPresent(AdminUserDO::getDeptId, deptIds)
.orderByDesc(AdminUserDO::getId));
}4.4 批量操作
java
// 批量插入
userMapper.insertBatch(userList);
// 批量更新
userMapper.updateBatch(userList);
// 批量删除
userMapper.deleteBatchIds(ids);5. 接口开发规范
5.1 RESTful API规范
| 操作 | HTTP方法 | 路径 | 示例 |
|---|---|---|---|
| 新增 | POST | /{module}/{domain}/create | POST /system/user/create |
| 修改 | PUT | /{module}/{domain}/update | PUT /system/user/update |
| 删除 | DELETE | /{module}/{domain}/delete | DELETE /system/user/delete?id=1 |
| 查询详情 | GET | /{module}/{domain}/get | GET /system/user/get?id=1 |
| 查询列表 | GET | /{module}/{domain}/list | GET /system/user/list |
| 查询分页 | GET | /{module}/{domain}/page | GET /system/user/page |
5.2 请求参数规范
5.2.1 路径参数
java
@GetMapping("/get")
@Operation(summary = "获得用户")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<UserRespVO> getUser(@RequestParam("id") Long id) {
return success(userService.getUser(id));
}5.2.2 请求体参数
java
@PostMapping("/create")
@Operation(summary = "新增用户")
public CommonResult<Long> createUser(@Valid @RequestBody UserSaveReqVO reqVO) {
Long id = userService.createUser(reqVO);
return success(id);
}5.2.3 查询参数
java
@GetMapping("/page")
@Operation(summary = "获得用户分页列表")
public CommonResult<PageResult<UserRespVO>> getUserPage(@Valid UserPageReqVO pageReqVO) {
PageResult<AdminUserDO> pageResult = userService.getUserPage(pageReqVO);
return success(pageResult);
}5.3 响应结果规范
使用统一的响应结果 CommonResult:
java
// 成功响应
return success(data);
// 成功响应(无数据)
return success(true);
// 失败响应
throw exception(USER_NOT_EXISTS);5.4 分页响应规范
使用统一的分页结果 PageResult:
java
PageResult<AdminUserDO> pageResult = userService.getUserPage(pageReqVO);
return success(pageResult);6. 注解使用规范
6.1 Spring注解
| 注解 | 用途 | 示例 |
|---|---|---|
| @RestController | 标记REST控制器 | @RestController |
| @RequestMapping | 定义请求路径 | @RequestMapping("/system/user") |
| @GetMapping | GET请求 | @GetMapping("/get") |
| @PostMapping | POST请求 | @PostMapping("/create") |
| @PutMapping | PUT请求 | @PutMapping("/update") |
| @DeleteMapping | DELETE请求 | @DeleteMapping("/delete") |
| @RequestParam | 请求参数 | @RequestParam("id") Long id |
| @RequestBody | 请求体 | @RequestBody UserSaveReqVO reqVO |
| @Autowired | 依赖注入 | @Autowired |
| @Resource | 依赖注入 | @Resource |
| @Service | 标记服务类 | @Service("adminUserService") |
| @Transactional | 事务控制 | @Transactional(rollbackFor = Exception.class) |
| @Valid | 参数校验 | @Valid @RequestBody UserSaveReqVO reqVO |
| @Validated | 参数校验 | @Validated |
6.2 MyBatis-Plus注解
| 注解 | 用途 | 示例 |
|---|---|---|
| @TableName | 指定表名 | @TableName("system_users") |
| @TableId | 标记主键 | @TableId |
| @TableField | 标记字段 | @TableField("user_name") |
| @KeySequence | 指定序列 | @KeySequence("system_users_seq") |
| @TableLogic | 逻辑删除 | @TableLogic |
6.3 Swagger注解
| 注解 | 用途 | 示例 |
|---|---|---|
| @Tag | API分组 | @Tag(name = "管理后台 - 用户") |
| @Operation | 接口说明 | @Operation(summary = "新增用户") |
| @Parameter | 参数说明 | @Parameter(name = "id", description = "编号") |
6.4 自定义注解
| 注解 | 用途 | 示例 |
|---|---|---|
| @PreAuthorize | 权限控制 | @PreAuthorize("@ss.hasPermission('system:user:create')") |
| @LogRecord | 操作日志 | @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE) |
| @ApiAccessLog | 访问日志 | @ApiAccessLog(operateType = CREATE) |
7. 异常处理规范
7.1 业务异常
使用 ServiceException 抛出业务异常:
java
import static com.fanyi.cloud.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.fanyi.cloud.module.system.enums.ErrorCodeConstants.USER_USERNAME_EXISTS;
private void validateUserExists(String username) {
AdminUserDO user = userMapper.selectByUsername(username);
if (user != null) {
throw exception(USER_USERNAME_EXISTS);
}
}7.2 错误码定义
在 ErrorCodeConstants 中定义错误码:
java
public interface ErrorCodeConstants {
ErrorCode USER_USERNAME_EXISTS = new ErrorCode(1_001_000_000, "用户名已存在");
ErrorCode USER_NOT_EXISTS = new ErrorCode(1_001_000_001, "用户不存在");
ErrorCode USER_PASSWORD_ERROR = new ErrorCode(1_001_000_002, "密码错误");
}7.3 全局异常处理
使用框架提供的全局异常处理器,统一处理异常并返回错误信息。
8. 日志规范
8.1 日志级别
| 级别 | 用途 | 示例 |
|---|---|---|
| ERROR | 错误日志 | log.error("用户创建失败", e); |
| WARN | 警告日志 | log.warn("用户名已存在"); |
| INFO | 信息日志 | log.info("用户创建成功,userId={}", userId); |
| DEBUG | 调试日志 | log.debug("查询条件:{}", wrapper); |
8.2 日志使用
java
@Slf4j
public class UserServiceImpl implements UserService {
public Long createUser(UserSaveReqVO reqVO) {
log.info("[createUser][开始创建用户,username={}]", reqVO.getUsername());
try {
Long id = doCreateUser(reqVO);
log.info("[createUser][用户创建成功,userId={}]", id);
return id;
} catch (Exception e) {
log.error("[createUser][用户创建失败,username={}]", reqVO.getUsername(), e);
throw e;
}
}
}8.3 操作日志
使用 @LogRecord 注解记录操作日志:
java
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}",
success = CREATE_SUCCESS)
public Long createUser(UserSaveReqVO createReqVO) {
// 业务逻辑
}9. 参数校验规范
9.1 基础校验注解
| 注解 | 用途 | 示例 |
|---|---|---|
| @NotNull | 不能为null | @NotNull private Long id; |
| @NotEmpty | 不能为空 | @NotEmpty private String name; |
| @NotBlank | 不能为空白 | @NotBlank private String username; |
| @Size | 长度校验 | @Size(min = 1, max = 20) private String username; |
| @Min | 最小值 | @Min(0) private Integer age; |
| @Max | 最大值 | @Max(150) private Integer age; |
| 邮箱格式 | @Email private String email; | |
| @Pattern | 正则校验 | @Pattern(regexp = "^1[3-9]\d{9}$") private String mobile; |
9.2 自定义校验
java
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MobileValidator.class)
public @interface Mobile {
String message() default "手机号格式不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}9.3 分组校验
java
public interface CreateGroup {}
public interface UpdateGroup {}
public class UserSaveReqVO {
@Null(groups = CreateGroup.class)
@NotNull(groups = UpdateGroup.class)
private Long id;
@NotBlank(groups = {CreateGroup.class, UpdateGroup.class})
private String username;
}10. 事务管理规范
10.1 事务注解
java
@Transactional(rollbackFor = Exception.class)
public void createUser(UserSaveReqVO reqVO) {
// 业务逻辑
}10.2 事务传播行为
java
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
// 默认传播行为
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// 创建新事务
}10.3 事务隔离级别
java
@Transactional(isolation = Isolation.READ_COMMITTED)
public void method() {
// 读已提交
}11. 权限控制规范
11.1 接口权限
使用 @PreAuthorize 注解控制接口权限:
java
@PreAuthorize("@ss.hasPermission('system:user:create')")
public CommonResult<Long> createUser(@Valid @RequestBody UserSaveReqVO reqVO) {
// 业务逻辑
}11.2 数据权限
使用数据权限注解控制数据访问范围:
java
@DataPermission(enable = true)
public PageResult<AdminUserDO> getUserPage(UserPageReqVO pageReqVO) {
// 业务逻辑
}12. 代码注释规范
12.1 类注释
java
/**
* 管理后台的用户 Service 实现类
*
* @author 芋道源码
*/
@Service("adminUserService")
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {
// ...
}12.2 方法注释
java
/**
* 创建用户
*
* @param createReqVO 创建信息
* @return 用户编号
*/
public Long createUser(UserSaveReqVO createReqVO) {
// ...
}12.3 字段注释
java
/**
* 用户ID
*/
@TableId
private Long id;
/**
* 用户账号
*/
private String username;
/**
* 加密后的密码
*/
private String password;13. 性能优化规范
13.1 批量操作
java
// 批量插入
userMapper.insertBatch(userList);
// 批量更新
userMapper.updateBatch(userList);13.2 缓存使用
java
@Cacheable(cacheNames = "user", key = "#id")
public UserRespVO getUser(Long id) {
// 业务逻辑
}
@CacheEvict(cacheNames = "user", key = "#id")
public void updateUser(UserSaveReqVO reqVO) {
// 业务逻辑
}13.3 懒加载
java
@Lazy
private TenantService tenantService;13.4 分页查询
java
// 使用分页查询,避免全表扫描
PageResult<AdminUserDO> pageResult = userMapper.selectPage(reqVO, wrapper);14. 安全规范
14.1 密码加密
java
@Resource
private PasswordEncoder passwordEncoder;
public void createUser(UserSaveReqVO reqVO) {
String encodedPassword = passwordEncoder.encode(reqVO.getPassword());
user.setPassword(encodedPassword);
}14.2 SQL注入防护
使用 MyBatis-Plus 的 Lambda 查询,避免 SQL 注入:
java
new LambdaQueryWrapperX<AdminUserDO>()
.eq(AdminUserDO::getUsername, username)14.3 XSS防护
使用框架提供的 XSS 过滤器,防止 XSS 攻击。
15. 测试规范
15.1 单元测试
java
@SpringBootTest
class UserServiceTest {
@Resource
private AdminUserService userService;
@Test
void testCreateUser() {
UserSaveReqVO reqVO = new UserSaveReqVO();
reqVO.setUsername("test");
Long id = userService.createUser(reqVO);
assertNotNull(id);
}
}15.2 集成测试
java
@SpringBootTest
@AutoConfigureMockMvc
class UserControllerTest {
@Resource
private MockMvc mockMvc;
@Test
void testCreateUser() throws Exception {
UserSaveReqVO reqVO = new UserSaveReqVO();
reqVO.setUsername("test");
mockMvc.perform(post("/system/user/create")
.contentType(MediaType.APPLICATION_JSON)
.content(JSON.toJSONString(reqVO)))
.andExpect(status().isOk());
}
}16. 版本控制规范
16.1 Git提交规范
提交信息格式:<type>(<scope>): <subject>
| 类型 | 说明 | 示例 |
|---|---|---|
| feat | 新功能 | feat(user): 添加用户创建接口 |
| fix | 修复bug | fix(user): 修复用户查询bug |
| docs | 文档 | docs(readme): 更新README文档 |
| style | 代码格式 | style(user): 代码格式调整 |
| refactor | 重构 | refactor(user): 重构用户服务 |
| test | 测试 | test(user): 添加用户测试 |
| chore | 构建/工具 | chore(deps): 更新依赖版本 |
16.2 分支规范
| 分支类型 | 命名规则 | 示例 |
|---|---|---|
| 主分支 | main | main |
| 开发分支 | develop | develop |
| 功能分支 | feature/ | feature/user-login |
| 修复分支 | fix/ | fix/user-login-error |
| 发布分支 | release/ | release/v1.0.0 |
17. 常见问题
17.1 如何处理循环依赖?
使用 @Lazy 注解延迟加载:
java
@Resource
@Lazy
private TenantService tenantService;17.2 如何处理大事务?
将大事务拆分为多个小事务:
java
@Transactional(rollbackFor = Exception.class)
public void bigTransaction() {
methodA();
methodB();
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodA() {
// 小事务
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// 小事务
}17.3 如何处理并发问题?
使用乐观锁:
java
@Version
private Integer version;使用悲观锁:
java
@Transactional
public void updateWithLock(Long id) {
AdminUserDO user = userMapper.selectByIdForUpdate(id);
// 业务逻辑
userMapper.updateById(user);
}注意:本文档持续更新中,如有问题请及时反馈。
