Java 后端代码规范
本文档定义 Java 后端项目的通用代码规范,基于阿里巴巴开发规约和业界最佳实践。
代码风格
- 使用 4 空格缩进
- 左花括号前留一个空格
- 每行最多 120 字符
- 字段、方法、类访问修饰符顺序:
private >protected >public - 不要使用尾行注释(行末的
// comment) - 工具类优先使用 Hutool
- 缩进使用空格,禁止使用 Tab
命名规范
常用命名
| 类型 | 规范 | 示例 |
|---|---|---|
| 项目名 | 小写字母,多个单词用 - 分隔 | my-project |
| 包名 | 全小写 | com.example.project |
| 类名 | UpperCamelCase | UserController |
| 方法名 | lowerCamelCase | getById, page |
| 变量名 | lowerCamelCase | userId, isDeleted |
| 常量名 | 全大写,下划线分隔 | MAX_PAGE_SIZE, DEFAULT_STATUS |
| 枚举 | UpperCamelCase,枚举值全大写下划线分隔 | Status.ENABLED, USER_TYPE_VIP |
类命名
| 类型 | 规范 | 示例 |
|---|---|---|
| Controller | {Entity}Controller / {Entity}AdminController | UserController |
| Service接口 | {Entity}Service | UserService |
| Service实现 | {Entity}ServiceImpl | UserServiceImpl |
| Mapper | {Entity}Mapper | UserMapper |
| Entity | 驼峰命名 | User |
| DTO | {Entity}QueryDTO, {Entity}DTO | UserQueryDTO |
| VO | {Entity}VO | UserVO |
| 工具类 | XxxUtil 或 XxxTool | StringUtil, DateUtil |
字段命名
- 数据库字段:下划线命名
user_id,created_at - Java 字段:驼峰命名
userId - 布尔字段:避免
is 前缀,如deleted 而非isDeleted(与数据库映射时注意) - 集合:
List 后缀userList,Map 后缀userMap
注解使用
Controller 注解
@Tag(name = "用户管理", description = "用户相关接口") // API 文档分类
@Slf4j
@RestController
@RequestMapping("/api/user")
@RequiredArgsConstructor
public class UserController {
@Operation(summary = "获取用户列表", description = "分页获取用户列表") // API 操作描述
@GetMapping("/list")
public Result<List<User>> list() {
// ...
}
@Operation(summary = "分页查询用户")
@PostMapping("/page")
public Result<PageResult<User>> page(@RequestBody UserQueryDTO queryDTO) {
// ...
}
@Operation(summary = "根据ID获取用户")
@Parameter(description = "用户ID") // 路径参数描述
@GetMapping("/{id}")
public Result<User> getById(@PathVariable Long id) {
// ...
}
@Operation(summary = "新增用户")
@PostMapping
public Result<Void> add(@Valid @RequestBody UserDTO dto) {
// ...
}
@Operation(summary = "更新用户")
@PutMapping
public Result<Void> update(@Valid @RequestBody UserDTO dto) {
// ...
}
@Operation(summary = "删除用户")
@Parameter(description = "用户ID")
@DeleteMapping("/{id}")
public Result<Void> delete(@PathVariable Long id) {
// ...
}
}
Entity/DTO 注解
@Data
@Schema(description = "用户实体") // 实体描述
public class User {
@Schema(description = "用户ID") // 字段描述
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@Schema(description = "用户名", example = "张三") // example 指定示例值
@NotBlank(message = "用户名不能为空")
@Size(max = 50, message = "用户名长度不能超过50")
private String username;
@Schema(description = "邮箱", example = "user@example.com")
@Email(message = "邮箱格式不正确")
private String email;
@Schema(description = "手机号", example = "13800138000")
private String phone;
@Schema(description = "状态", allowableValues = {"0", "1"}) // 可选值
private Integer status;
@Schema(description = "创建时间", accessMode = Schema.AccessMode.READ_ONLY) // 只读字段
private LocalDateTime createdAt;
}
注解说明
| 类型 | 注解 | 说明 |
|---|---|---|
| Controller类 | @Tag | API 分类标签,用于分组 |
| Controller方法 | @Operation | API 操作描述,summary 为简短描述,description 为详细描述 |
| Controller方法 | @Parameter | 参数描述,用于 PathVariable 和 Query 参数 |
| Entity/DTO类 | @Schema | 实体/DTO 描述 |
| Entity/DTO字段 | @Schema | 字段描述、示例值、取值范围 |
| 参数校验 | @Valid | 启用参数校验 |
| Service实现 | @Service | 服务层标记 |
| 日志 | @Slf4j | 日志标记 |
@Schema 常用属性
@Schema(
description = "描述", // 字段描述
example = "示例值", // 示例值
requiredMode = RequiredMode.REQUIRED, // 是否必填
allowableValues = {"0", "1", "2"}, // 可选值列表
minLength = 1, // 最小长度
maxLength = 50, // 最大长度
minimum = "0", // 最小值
maximum = "100", // 最大值
accessMode = Schema.AccessMode.READ_ONLY // 访问模式(READ_ONLY 只读)
)
SpringDoc 依赖
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
接口文档访问
- Swagger UI:
http://host:port/swagger-ui.html - OpenAPI Docs:
http://host:port/v3/api-docs
参数校验
使用 @Valid 和校验注解对输入参数进行验证:
@PostMapping
public Result<Void> add(@Valid @RequestBody UserDTO dto) {
// ...
}
@Data
@Schema(description = "用户DTO")
public class UserDTO {
@NotBlank(message = "名称不能为空")
@Size(max = 50, message = "名称长度不能超过50")
private String name;
@NotNull(message = "ID不能为空")
private Long id;
@Min(value = 0, message = "值不能为负数")
@Max(value = 1000, message = "值不能超过1000")
private Integer value;
}
常用校验注解:
-
@NotNull:不能为 null -
@NotBlank:不能为空白字符串 -
@NotEmpty:不能为 null 或空集合 -
@Size:字符串/集合长度范围 -
@Min/@Max:数值范围 -
@Email:邮箱格式 -
@Pattern:正则表达式
事务管理
增删改操作必须添加 @Transactional,并指定异常回滚:
@Transactional(rollbackFor = Exception.class)
public void update(User user) {
userService.updateById(user);
}
异常处理
原则
- 不要 catch
Throwable 或Exception - 记录完整异常堆栈:
log.error("错误信息", e) - 不要只记录异常消息:
log.error(e.getMessage())会丢失堆栈 - 敏感信息脱敏后再记录
推荐模式
try {
userService.save(user);
log.info("【模块名】操作成功: id={}", user.getId());
} catch (Exception e) {
log.error("【模块名】操作异常: ", e);
return Result.error("操作失败");
}
自定义业务异常
public class BusinessException extends RuntimeException {
private final Integer code;
public BusinessException(String message) {
super(message);
this.code = 500;
}
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
}
}
日志规范
格式
使用 Slf4j 日志,格式为 【模块名】操作描述:
log.info("【用户管理】获取用户列表请求");
log.info("【用户管理】获取用户列表成功, 数量: {}", list.size());
log.warn("【用户管理】参数验证失败: {}", errorMessage);
log.error("【用户管理】查询异常: ", e);
占位符
日志参数使用占位符 {},禁止字符串拼接:
// 禁止
log.debug("用户" + userId + "登录成功");
// 推荐
log.debug("用户 {} 登录成功", userId);
敏感信息脱敏
String maskedPhone = phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
log.info("用户 {} 手机号更新为 {}", userId, maskedPhone);
分页查询模式
@Operation(summary = "分页查询用户")
@PostMapping("/page")
public Result<PageResult<User>> page(@RequestBody UserQueryDTO queryDTO) {
Page<User> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
if (queryDTO.getName() != null) {
wrapper.like(User::getName, queryDTO.getName());
}
wrapper.orderByDesc(User::getCreatedAt);
Page<User> result = userService.page(page, wrapper);
return Result.success(PageResult.of(result));
}
常量定义
使用枚举
public enum Status {
DRAFT(1, "草稿"),
ENABLED(2, "启用"),
DISABLED(3, "禁用");
private final int code;
private final String desc;
Status(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
public static Status fromCode(int code) {
for (Status status : values()) {
if (status.code == code) {
return status;
}
}
return null;
}
}
避免魔法值
// 禁止
if (status == 1) {
// ...
}
// 推荐
if (Status.ENABLED.getCode() == status) {
// ...
}
方法设计
原则
- 单一职责:每个方法只做一件事
- 方法长度:单个方法不超过 50 行
- 参数数量:不超过 5 个参数,超过时使用对象封装
卫语句提前返回
public void process(User user) {
if (user == null) {
return;
}
// 正常业务逻辑
}
集合处理
遍历
// 推荐:for-each
for (User user : userList) {
// ...
}
// 推荐:Stream API
List<Long> ids = userList.stream()
.map(User::getId)
.collect(Collectors.toList());
判空
// Hutool 判空
if (CollUtil.isEmpty(userList)) {
return;
}
// 或
if (userList == null || userList.isEmpty()) {
return;
}
字符串处理
避免字符串拼接
// 禁止:循环内字符串拼接
String s = "";
for (String item : list) {
s += item;
}
// 推荐:StringBuilder
StringBuilder sb = new StringBuilder();
for (String item : list) {
sb.append(item);
}
String s = sb.toString();
// 推荐:Hutool
String s = StrUtil.join(list, ",");
判空去空
// Hutool 字符串工具
StrUtil.isBlank(str); // 是否空白
StrUtil.isNotBlank(str); // 是否非空白
StrUtil.trim(str); // 去首尾空白
StrUtil.blankToDefault(str, "默认"); // 空白时默认值
Optional 使用
// 避免
String name = null;
if (user != null) {
name = user.getName();
}
// 推荐
String name = Optional.ofNullable(user)
.map(User::getName)
.orElse("匿名");
Lombok 使用
@Data
适用于 Entity、DTO、VO:
@Data
@Schema(description = "用户DTO")
public class UserDTO {
private Long id;
private String name;
}
@Builder
复杂对象构造时使用:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
private Long id;
private String name;
}
// 使用
UserDTO dto = UserDTO.builder()
.id(1L)
.name("测试")
.build();
数据库规范
字段命名
- 使用下划线命名:
user_id,created_at,is_deleted - 主键:
id - 时间字段:
created_at,updated_at,deleted_at - 软删除:
is_deleted
基础实体
项目中的基础实体类应包含:
@Data
public class BaseEntity {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@TableField("created_by")
private String createdBy;
@TableField("created_at")
private LocalDateTime createdAt;
@TableField("updated_by")
private String updatedBy;
@TableField("updated_at")
private LocalDateTime updatedAt;
@TableField("is_deleted")
private Boolean isDeleted;
@TableField("deleted_at")
private LocalDateTime deletedAt;
}
数据库迁移
- 迁移文件放在指定目录
- 命名:
V{version}__{description}.sql - 版本号递增,不要修改已执行的迁移文件
禁止项
- 禁止使用
System.out.println()输出日志 - 禁止在循环体内声明大对象
- 禁止使用
new Date(),使用LocalDateTime.now() - 禁止使用
select *,明确指定查询字段 - 禁止在 Service 层直接操作 Map/List 等集合做业务处理
- 禁止使用可变参数作为方法重载
- 禁止使用
Thread.sleep()替代等待逻辑 - 禁止在生产环境使用日志级别
debug
Rules 分享-Java 后端代码规范
https://blog.xiao6.top/archives/1776585451180
Comments