8.3 KiB
8.3 KiB
Java 代码风格规范
通用 Java 项目代码风格规范,适用于所有 Java 后端项目。
1. 项目结构
包组织
- 基础包按公司域名倒写 + 项目名,如
com.company.project - 按业务域划分模块,如
user/、order/、product/
目录结构(各模块内)
controller/ # 控制层
service/ # 服务层接口
service/impl/ # 服务层实现
entity/ # 实体层
entity/dto/ # 数据传输对象
entity/vo/ # 视图对象
mapper/ # 数据访问层(MyBatis/JPA)
manager/ # 复杂业务编排
checker/ # 业务校验工具
2. 命名规范
| 元素 | 规范 | 示例 |
|---|---|---|
| 类名 | PascalCase,2-41字符 | UserService、OrderController |
| 方法名 | camelCase,1-31字符 | getUserById()、saveOrder() |
| 变量名 | camelCase | userId、orderList |
| 常量 | UPPER_SNAKE_CASE | MAX_RETRY_COUNT、DEFAULT_PAGE_SIZE |
| 包名 | 全小写,dot分隔 | com.company.project.common.util |
特定后缀/前缀
- Service 接口:前缀
I,如IUserService - Service 实现:后缀
Impl,如UserServiceImpl - DTO:后缀
Dto或DTO - VO:后缀
VO - 查询参数对象:后缀
Query或Criteria - 校验工具类:后缀
Checker或Validator - Manager:后缀
Manager(复杂业务编排层)
3. 代码格式
- 缩进:4空格(禁止Tab)
- 行长度:最大120-200字符
- 花括号:K&R风格(同一行开括号)
- 文件最大行数:通常不超过2000行
- 方法最大行数:通常不超过150-300行
- 参数数量:最多7-9个(超出考虑封装为对象)
- if嵌套深度:最多3-4层(超出考虑提取方法)
4. 注释规范
类级Javadoc
/**
* 用户服务类
*
* <p>提供用户注册、登录、信息管理等核心功能</p>
*
* @author authorName
* @since 2024-01-01
*/
方法级Javadoc
/**
* 根据用户ID获取用户信息
*
* @param userId 用户ID
* @return 用户信息,不存在返回null
* @author authorName
* @since 2024年1月1日 00:00:00
*/
public User getUserById(String userId) { }
字段注释
/** 用户ID */
private String userId;
行内注释
- 注释放在代码上方或行尾
- 复杂业务逻辑需注释说明
5. 异常处理
异常使用原则
- 业务异常使用自定义异常(如
BusinessException) - 参数校验异常使用
IllegalArgumentException或专用校验异常 - 系统异常使用
RuntimeException包装
全局异常处理
@ControllerAdvice
@RestController
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public Result<?> handleBusinessException(BusinessException e) {
return Result.error(e.getCode(), e.getMessage());
}
}
日志记录
log.info("用户登录成功,userId={}", userId);
log.warn("订单处理超时,orderId={}", orderId);
log.error("数据库连接失败", e);
6. 常用代码模式
DTO/Request/Response
@Data
@Accessors(chain = true)
public class UserDTO implements Serializable {
@NotBlank(message = "用户名不能为空")
private String username;
@NotNull(message = "年龄不能为空")
@Min(value = 0, message = "年龄不能为负数")
private Integer age;
}
Entity
@Data
@Entity
@Table(name = "t_user")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String id;
@Column(name = "username")
private String username;
}
Service
public interface IUserService {
User getUserById(String userId);
}
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements IUserService {
private final IUserMapper userMapper;
@Override
public User getUserById(String userId) {
return userMapper.selectById(userId);
}
}
Controller
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
public class UserController {
private final IUserService userService;
@GetMapping("/{id}")
public Result<User> getUserById(@PathVariable String id) {
return Result.ok(userService.getUserById(id));
}
}
校验工具
public class UserValidator {
public static List<String> validate(UserDTO dto) {
List<String> errors = new ArrayList<>();
if (dto.getUsername() == null || dto.getUsername().isBlank()) {
errors.add("用户名不能为空");
}
return errors;
}
}
Enum
@Getter
@AllArgsConstructor
public enum UserStatus {
ENABLE("启用", "enable"),
DISABLE("禁用", "disable");
private final String desc;
private final String code;
public static UserStatus getByCode(String code) {
return Arrays.stream(values())
.filter(e -> e.getCode().equals(code))
.findFirst()
.orElse(null);
}
}
常量类
public interface UserConstants {
int DEFAULT_PAGE_SIZE = 10;
int MAX_PAGE_SIZE = 100;
String DEFAULT_STATUS = "enable";
}
7. API设计规范
HTTP方法约束
强制约束:只能使用 GET 和 POST 方法
| 操作 | 方法 | 路径 |
|---|---|---|
| 查询 | GET | /users/{id} |
| 列表 | GET | /users?name={name} |
| 新增 | POST | /users |
| 更新 | POST + /update |
/users/update |
| 删除 | POST + /remove |
/users/remove |
| 部分更新 | POST + /patch |
/users/patch |
说明:禁止使用 PUT、DELETE、PATCH 等其他HTTP方法。所有非GET请求均使用POST方法,通过路径后缀区分操作类型。
统一响应格式
公司基础框架提供 RestResult<T> 统一响应格式:
return RestResult.ok(data); // 成功
return RestResult.ok(); // 无返回值的成功
return RestResult.error(ResultCode.DATA_NONE); // 错误(根据错误码)
return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, "自定义错误信息");
说明:
RestResult<T>是公司基础框架的核心组件,所有API响应必须使用该格式,不可自行定义其他响应格式。
统一响应格式
public class RestResult<T> {
private int code;
private String message;
private T data;
public static <T> RestResult<T> ok(T data) { }
public static <T> RestResult<T> error(String message) { }
public static <T> RestResult<T> error(int code, String message) { }
}
8. 事务处理
@Transactional(rollbackFor = Exception.class)
public void saveUser(User user) {
userMapper.insert(user);
// 其他操作
}
9. API文档注解
Swagger/OpenAPI 3.0
@Api(tags = "用户管理")
@RestController
@RequestMapping("/users")
public class UserController {
@ApiOperation("根据ID获取用户")
@GetMapping("/{id}")
public RestResult<User> getUser(@ApiParam("用户ID") @PathVariable String id) { }
}
SpringDoc OpenAPI(推荐)
@Tag(name = "用户管理", description = "用户相关接口")
@RestController
@RequestMapping("/users")
public class UserController {
@Operation(summary = "根据ID获取用户")
@GetMapping("/{id}")
public RestResult<User> getUser(@Parameter(description = "用户ID") @PathVariable String id) { }
}
10. 禁止事项
- 禁止魔法数字:使用常量替代,如
MAX_RETRY_COUNT - 禁止无用的import:保持代码整洁
- 禁止长方法:方法不超过150行,拆分为多个小方法
- 禁止深度嵌套:if嵌套不超过3-4层
- 禁止硬编码:配置信息放入配置文件
- 禁止空指针:使用
Objects.requireNonNull()或 Optional - 禁止swallow异常:异常必须记录或重新抛出
11. 最佳实践
- 使用 Lombok 减少样板代码(
@Data、@Slf4j、@Service) - 使用
@RequiredArgsConstructor代替构造器注入 - 使用 Optional 处理可能为null的返回值
- 使用 Stream API 处理集合操作
- 接口方法参数不超过5个,超出使用DTO封装
- 日志记录使用占位符
{}而非字符串拼接