339 lines
8.3 KiB
Markdown
339 lines
8.3 KiB
Markdown
|
|
# 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
|
|||
|
|
```java
|
|||
|
|
/**
|
|||
|
|
* 用户服务类
|
|||
|
|
*
|
|||
|
|
* <p>提供用户注册、登录、信息管理等核心功能</p>
|
|||
|
|
*
|
|||
|
|
* @author authorName
|
|||
|
|
* @since 2024-01-01
|
|||
|
|
*/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 方法级Javadoc
|
|||
|
|
```java
|
|||
|
|
/**
|
|||
|
|
* 根据用户ID获取用户信息
|
|||
|
|
*
|
|||
|
|
* @param userId 用户ID
|
|||
|
|
* @return 用户信息,不存在返回null
|
|||
|
|
* @author authorName
|
|||
|
|
* @since 2024年1月1日 00:00:00
|
|||
|
|
*/
|
|||
|
|
public User getUserById(String userId) { }
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 字段注释
|
|||
|
|
```java
|
|||
|
|
/** 用户ID */
|
|||
|
|
private String userId;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 行内注释
|
|||
|
|
- 注释放在代码上方或行尾
|
|||
|
|
- 复杂业务逻辑需注释说明
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 异常处理
|
|||
|
|
|
|||
|
|
### 异常使用原则
|
|||
|
|
- 业务异常使用自定义异常(如 `BusinessException`)
|
|||
|
|
- 参数校验异常使用 `IllegalArgumentException` 或专用校验异常
|
|||
|
|
- 系统异常使用 `RuntimeException` 包装
|
|||
|
|
|
|||
|
|
### 全局异常处理
|
|||
|
|
```java
|
|||
|
|
@ControllerAdvice
|
|||
|
|
@RestController
|
|||
|
|
public class GlobalExceptionHandler {
|
|||
|
|
@ExceptionHandler(BusinessException.class)
|
|||
|
|
public Result<?> handleBusinessException(BusinessException e) {
|
|||
|
|
return Result.error(e.getCode(), e.getMessage());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 日志记录
|
|||
|
|
```java
|
|||
|
|
log.info("用户登录成功,userId={}", userId);
|
|||
|
|
log.warn("订单处理超时,orderId={}", orderId);
|
|||
|
|
log.error("数据库连接失败", e);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 常用代码模式
|
|||
|
|
|
|||
|
|
### DTO/Request/Response
|
|||
|
|
```java
|
|||
|
|
@Data
|
|||
|
|
@Accessors(chain = true)
|
|||
|
|
public class UserDTO implements Serializable {
|
|||
|
|
@NotBlank(message = "用户名不能为空")
|
|||
|
|
private String username;
|
|||
|
|
|
|||
|
|
@NotNull(message = "年龄不能为空")
|
|||
|
|
@Min(value = 0, message = "年龄不能为负数")
|
|||
|
|
private Integer age;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Entity
|
|||
|
|
```java
|
|||
|
|
@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
|
|||
|
|
```java
|
|||
|
|
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
|
|||
|
|
```java
|
|||
|
|
@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));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 校验工具
|
|||
|
|
```java
|
|||
|
|
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
|
|||
|
|
```java
|
|||
|
|
@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);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 常量类
|
|||
|
|
```java
|
|||
|
|
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>` 统一响应格式:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
return RestResult.ok(data); // 成功
|
|||
|
|
return RestResult.ok(); // 无返回值的成功
|
|||
|
|
return RestResult.error(ResultCode.DATA_NONE); // 错误(根据错误码)
|
|||
|
|
return RestResult.error(ResultCode.BUSINESS_LOGIC_ERROR, "自定义错误信息");
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
> **说明**:`RestResult<T>` 是公司基础框架的核心组件,所有API响应必须使用该格式,不可自行定义其他响应格式。
|
|||
|
|
|
|||
|
|
### 统一响应格式
|
|||
|
|
```java
|
|||
|
|
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. 事务处理
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
@Transactional(rollbackFor = Exception.class)
|
|||
|
|
public void saveUser(User user) {
|
|||
|
|
userMapper.insert(user);
|
|||
|
|
// 其他操作
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. API文档注解
|
|||
|
|
|
|||
|
|
### Swagger/OpenAPI 3.0
|
|||
|
|
```java
|
|||
|
|
@Api(tags = "用户管理")
|
|||
|
|
@RestController
|
|||
|
|
@RequestMapping("/users")
|
|||
|
|
public class UserController {
|
|||
|
|
@ApiOperation("根据ID获取用户")
|
|||
|
|
@GetMapping("/{id}")
|
|||
|
|
public RestResult<User> getUser(@ApiParam("用户ID") @PathVariable String id) { }
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### SpringDoc OpenAPI(推荐)
|
|||
|
|
```java
|
|||
|
|
@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封装
|
|||
|
|
- 日志记录使用占位符 `{}` 而非字符串拼接
|