# Java代码规范 ## 1. 命名规范 ### 1.1 包命名 - 包名全部小写,使用点分隔 - 示例:`com.emotionmuseum.user.controller` ### 1.2 类命名 - 使用大驼峰命名法(PascalCase) - 示例:`UserController`、`UserService` ### 1.3 方法命名 - 使用小驼峰命名法(camelCase) - 示例:`getUserById`、`createUser` ### 1.4 变量命名 - 使用小驼峰命名法(camelCase) - 常量使用全大写+下划线(UPPER_SNAKE_CASE) - 示例:`userName`、`MAX_RETRY_COUNT` ## 2. 导入包规范 ### 2.1 导入方式规范 **重要原则:必须使用常规的import方式导入类,严禁在代码中使用全路径限定名方式导入类。** #### 2.1.1 正确的导入方式 ```java // ✅ 正确示例:使用import语句导入类 import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.beans.factory.annotation.Autowired; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import com.emotionmuseum.dto.request.CreateUserRequest; import com.emotionmuseum.dto.response.UserResponse; import com.emotionmuseum.service.UserService; import com.emotionmuseum.common.result.Result; @RestController @RequestMapping("/api/users") @RequiredArgsConstructor @Slf4j public class UserController { private final UserService userService; @PostMapping public Result createUser(@RequestBody CreateUserRequest request) { UserResponse response = userService.createUser(request); return Result.success(response); } } ``` #### 2.1.2 错误的导入方式 ```java // ❌ 错误示例:在代码中使用全路径限定名 public class UserController { @org.springframework.beans.factory.annotation.Autowired private com.emotionmuseum.service.UserService userService; @org.springframework.web.bind.annotation.PostMapping public com.emotionmuseum.common.result.Result createUser(@org.springframework.web.bind.annotation.RequestBody com.emotionmuseum.dto.request.CreateUserRequest request) { com.emotionmuseum.dto.response.UserResponse response = userService.createUser(request); return com.emotionmuseum.common.result.Result.success(response); } } ``` ### 2.2 导入顺序规范 ```java // 1. Java标准库导入 import java.time.LocalDateTime; import java.util.List; import java.util.UUID; // 2. 第三方库导入(按字母顺序) import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; // 3. 项目内部导入(按包层次顺序) import com.emotionmuseum.common.result.Result; import com.emotionmuseum.dto.request.CreateUserRequest; import com.emotionmuseum.dto.response.UserResponse; import com.emotionmuseum.service.UserService; ``` ### 2.3 导入优化规范 ```java // ✅ 推荐:使用通配符导入相关的类 import org.springframework.web.bind.annotation.*; // ✅ 推荐:分别导入不同包的类 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; // ❌ 不推荐:过度使用通配符导入 import org.springframework.*; // ❌ 不推荐:导入未使用的类 import java.util.ArrayList; // 如果代码中没有使用ArrayList ``` ### 2.4 静态导入规范 ```java // ✅ 正确:静态导入常用的静态方法 import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; // ✅ 正确:静态导入项目中的工具类方法 import static com.emotionmuseum.common.util.DateUtil.formatDateTime; import static com.emotionmuseum.common.util.StringUtil.isBlank; // ❌ 错误:避免过度使用静态导入 import static java.lang.Math.*; import static java.util.Collections.*; ``` ### 2.5 导入冲突处理 ```java // 当出现类名冲突时,使用import别名或明确指定包名 import com.emotionmuseum.dto.response.Result; import org.springframework.http.ResponseEntity; public class UserController { // 使用别名避免冲突 public com.emotionmuseum.dto.response.Result createUser() { // 业务逻辑 } // 或者使用import别名(如果IDE支持) // import com.emotionmuseum.dto.response.Result as EmotionResult; } ``` ## 3. 代码结构规范 ### 3.1 类结构顺序 ```java public class ExampleClass { // 1. 静态常量 public static final String CONSTANT = "value"; // 2. 实例变量 private String instanceVariable; // 3. 构造方法 public ExampleClass() {} // 4. 公共方法 public void publicMethod() {} // 5. 私有方法 private void privateMethod() {} } ``` ### 3.2 方法结构 ```java public Result getUserById(Long userId) { // 1. 参数校验 if (userId == null) { throw new IllegalArgumentException("用户ID不能为空"); } // 2. 业务逻辑 User user = userService.getById(userId); // 3. 数据转换 UserResponse response = UserConverter.toResponse(user); // 4. 返回结果 return Result.success(response); } ``` ## 4. 注释规范 ### 4.1 类注释 ```java /** * 用户控制器 * * @author 作者名 * @since 1.0.0 */ @RestController public class UserController { } ``` ### 4.2 方法注释 ```java /** * 根据用户ID获取用户信息 * * @param userId 用户ID * @return 用户信息响应对象 * @throws UserNotFoundException 当用户不存在时抛出 */ public Result getUserById(Long userId) { } ``` ## 5. 异常处理规范 ### 5.1 异常定义 ```java public class UserNotFoundException extends BusinessException { public UserNotFoundException(String message) { super(message); } } ``` ### 5.2 异常抛出 ```java if (user == null) { throw new UserNotFoundException("用户不存在,ID: " + userId); } ``` ## 6. Log4j2日志规范 ### 6.1 日志级别使用 ```java // FATAL: 致命错误,系统无法继续运行 logger.fatal("系统严重错误,无法继续运行", e); // ERROR: 系统错误 logger.error("数据库连接失败", e); // WARN: 警告信息 logger.warn("用户{}尝试访问未授权资源", userId); // INFO: 重要业务信息 logger.info("用户{}登录成功", username); // DEBUG: 调试信息 logger.debug("查询用户参数: {}", queryParams); // TRACE: 详细调试信息 logger.trace("进入方法: {}", methodName); ``` ### 6.2 日志记录规范 ```java // 使用占位符,避免字符串拼接 logger.info("用户{}在{}登录成功", username, LocalDateTime.now()); // 异常日志记录 try { // 业务逻辑 } catch (Exception e) { logger.error("处理用户请求失败,用户ID: {}, 错误信息: {}", userId, e.getMessage(), e); throw new BusinessException("处理失败"); } // 性能日志记录 long startTime = System.currentTimeMillis(); // 业务逻辑 long endTime = System.currentTimeMillis(); logger.info("查询用户信息耗时: {}ms", endTime - startTime); ``` ### 6.3 MDC日志追踪 ```java // 设置MDC信息 MDC.put("userId", userId.toString()); MDC.put("requestId", UUID.randomUUID().toString()); try { // 业务逻辑 } finally { // 清理MDC MDC.clear(); } ``` ## 7. 数据库操作规范 ### 7.1 MyBatis-Plus使用 ```java // 查询单个 User user = userMapper.selectById(userId); // 条件查询 List users = userMapper.selectList( new LambdaQueryWrapper() .eq(User::getStatus, UserStatus.ACTIVE) .orderByDesc(User::getCreateTime) ); ``` ## 8. 接口设计规范 ### 8.1 Controller层规范 **重要原则:Controller层只负责接收请求、参数校验、调用Service层、返回结果,严禁在Controller层编写任何业务逻辑代码。** ```java @RestController @RequestMapping("/api/users") @Validated @Slf4j public class UserController { @Autowired private UserService userService; @PostMapping public Result createUser(@Valid @RequestBody CreateUserRequest request) { // Controller层只做:参数校验(通过@Valid)、调用Service、返回结果 UserResponse response = userService.createUser(request); return Result.success(response); } @GetMapping("/{id}") public Result getUserById(@PathVariable Long id) { // Controller层只做:调用Service、返回结果 UserResponse response = userService.getUserById(id); return Result.success(response); } @PutMapping("/{id}") public Result updateUser(@PathVariable Long id, @Valid @RequestBody UpdateUserRequest request) { // Controller层只做:参数校验、调用Service、返回结果 UserResponse response = userService.updateUser(id, request); return Result.success(response); } @DeleteMapping("/{id}") public Result deleteUser(@PathVariable Long id) { // Controller层只做:调用Service、返回结果 userService.deleteUser(id); return Result.success(null); } } ``` ### 8.2 Controller层禁止事项 ```java // ❌ 错误示例:在Controller层编写业务逻辑 @PostMapping("/users") public Result createUser(@Valid @RequestBody CreateUserRequest request) { // 错误:在Controller层进行业务判断 if (userMapper.selectByUsername(request.getUsername()) != null) { throw new BusinessException("用户名已存在"); } // 错误:在Controller层进行数据转换 User user = new User(); user.setUsername(request.getUsername()); user.setPassword(passwordEncoder.encode(request.getPassword())); // 错误:在Controller层直接操作数据库 userMapper.insert(user); // 错误:在Controller层进行复杂的数据处理 UserResponse response = new UserResponse(); response.setId(user.getId()); response.setUsername(user.getUsername()); return Result.success(response); } // ✅ 正确示例:Controller层只负责调用Service @PostMapping("/users") public Result createUser(@Valid @RequestBody CreateUserRequest request) { UserResponse response = userService.createUser(request); return Result.success(response); } ``` ### 8.3 请求响应对象规范 ```java @Data public class CreateUserRequest { @NotBlank(message = "用户名不能为空") private String username; @NotBlank(message = "密码不能为空") private String password; } @Data public class UserResponse { private Long id; private String username; private LocalDateTime createTime; } ``` ### 8.4 Service层业务逻辑规范 **重要原则:所有业务逻辑必须在Service层完成,包括数据校验、业务规则判断、数据处理、事务管理等。** ```java @Service @Transactional @Slf4j public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Autowired private PasswordEncoder passwordEncoder; @Override public UserResponse createUser(CreateUserRequest request) { // 1. 业务参数校验 validateCreateUserRequest(request); // 2. 业务规则判断 checkUserExists(request.getUsername()); // 3. 数据转换和业务处理 User user = convertToUser(request); user.setPassword(passwordEncoder.encode(request.getPassword())); // 4. 数据持久化 userMapper.insert(user); // 5. 返回结果转换 return convertToResponse(user); } @Override public UserResponse getUserById(Long id) { // 1. 参数校验 if (id == null) { throw new IllegalArgumentException("用户ID不能为空"); } // 2. 业务逻辑:查询用户 User user = userMapper.selectById(id); if (user == null) { throw new UserNotFoundException("用户不存在,ID: " + id); } // 3. 返回结果转换 return convertToResponse(user); } @Override public UserResponse updateUser(Long id, UpdateUserRequest request) { // 1. 参数校验 validateUpdateUserRequest(id, request); // 2. 业务逻辑:检查用户是否存在 User existingUser = userMapper.selectById(id); if (existingUser == null) { throw new UserNotFoundException("用户不存在,ID: " + id); } // 3. 业务规则判断 if (StringUtils.hasText(request.getUsername())) { checkUserExists(request.getUsername(), id); } // 4. 数据更新 updateUserFields(existingUser, request); userMapper.updateById(existingUser); // 5. 返回结果转换 return convertToResponse(existingUser); } @Override public void deleteUser(Long id) { // 1. 参数校验 if (id == null) { throw new IllegalArgumentException("用户ID不能为空"); } // 2. 业务逻辑:检查用户是否存在 User user = userMapper.selectById(id); if (user == null) { throw new UserNotFoundException("用户不存在,ID: " + id); } // 3. 业务规则判断:检查是否可以删除 checkUserCanBeDeleted(user); // 4. 执行删除 userMapper.deleteById(id); log.info("用户删除成功,ID: {}", id); } // 私有方法:业务校验 private void validateCreateUserRequest(CreateUserRequest request) { if (request == null) { throw new IllegalArgumentException("请求参数不能为空"); } // 其他业务校验逻辑 } private void checkUserExists(String username) { User existingUser = userMapper.selectByUsername(username); if (existingUser != null) { throw new BusinessException("用户名已存在: " + username); } } private void checkUserExists(String username, Long excludeId) { User existingUser = userMapper.selectByUsernameAndIdNot(username, excludeId); if (existingUser != null) { throw new BusinessException("用户名已存在: " + username); } } private void checkUserCanBeDeleted(User user) { // 检查用户是否可以删除的业务逻辑 if (user.getStatus() == UserStatus.ACTIVE) { // 检查是否有未完成的订单等 if (hasUnfinishedOrders(user.getId())) { throw new BusinessException("用户有未完成的订单,无法删除"); } } } // 私有方法:数据转换 private User convertToUser(CreateUserRequest request) { User user = new User(); user.setUsername(request.getUsername()); user.setEmail(request.getEmail()); user.setStatus(UserStatus.ACTIVE); return user; } private UserResponse convertToResponse(User user) { UserResponse response = new UserResponse(); response.setId(user.getId()); response.setUsername(user.getUsername()); response.setEmail(user.getEmail()); response.setStatus(user.getStatus()); response.setCreateTime(user.getCreateTime()); return response; } } ``` ## 9. 缓存使用规范 ### 9.1 Redis缓存注解 ```java @Cacheable(value = "user", key = "#userId") public UserResponse getUserById(Long userId) { // 业务逻辑 } @CacheEvict(value = "user", key = "#userId") public void updateUser(Long userId, UpdateUserRequest request) { // 更新逻辑 } ``` ## 10. 异步处理规范 ### 10.1 异步方法定义 ```java @Async("notificationExecutor") public CompletableFuture sendNotificationAsync(Long userId, String message) { try { sendNotification(userId, message); return CompletableFuture.completedFuture(null); } catch (Exception e) { logger.error("发送通知失败", e); return CompletableFuture.failedFuture(e); } } ``` ## 11. 单元测试规范 ### 11.1 测试类结构 ```java @ExtendWith(MockitoExtension.class) class UserServiceTest { @Mock private UserMapper userMapper; @InjectMocks private UserServiceImpl userService; @Test @DisplayName("根据ID获取用户 - 成功") void getUserById_Success() { // Given Long userId = 1L; User user = new User(); user.setId(userId); when(userMapper.selectById(userId)).thenReturn(user); // When UserResponse result = userService.getUserById(userId); // Then assertThat(result).isNotNull(); assertThat(result.getId()).isEqualTo(userId); } } ``` ## 12. Spring Security安全规范 ### 12.1 安全注解使用 ```java @RestController @RequestMapping("/api/users") public class UserController { @PreAuthorize("hasRole('ADMIN')") @GetMapping("/admin") public Result> getAllUsers() { // 只有ADMIN角色可以访问 } @PreAuthorize("hasRole('USER') and #userId == authentication.principal.id") @GetMapping("/{userId}") public Result getUserById(@PathVariable Long userId) { // 只有USER角色且只能访问自己的信息 } @PreAuthorize("permitAll()") @PostMapping("/register") public Result register(@Valid @RequestBody CreateUserRequest request) { // 允许所有人访问 } } ``` ### 12.2 输入验证 ```java @PostMapping("/users") public Result createUser(@Valid @RequestBody CreateUserRequest request) { return userService.createUser(request); } ``` ### 12.3 敏感信息处理 ```java // 日志中脱敏 logger.info("用户{}登录成功", maskUsername(username)); private String maskUsername(String username) { if (username == null || username.length() <= 2) { return username; } return username.substring(0, 1) + "***" + username.substring(username.length() - 1); } ``` ### 12.4 密码处理规范 ```java @Service public class UserServiceImpl implements UserService { @Autowired private PasswordEncoder passwordEncoder; public void createUser(CreateUserRequest request) { // 密码加密存储 String encodedPassword = passwordEncoder.encode(request.getPassword()); user.setPassword(encodedPassword); // 密码验证 if (passwordEncoder.matches(rawPassword, encodedPassword)) { // 密码正确 } } } ``` ### 12.5 JWT Token处理 ```java @Component public class JwtTokenProvider { public String generateToken(UserDetails userDetails) { return Jwts.builder() .setSubject(userDetails.getUsername()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + jwtExpirationMs)) .signWith(SignatureAlgorithm.HS512, jwtSecret) .compact(); } public String getUsernameFromToken(String token) { return Jwts.parser() .setSigningKey(jwtSecret) .parseClaimsJws(token) .getBody() .getSubject(); } } ``` ## 13. 版本控制规范 ### 13.1 Git提交规范 ```bash feat(user): 添加用户注册功能 fix(auth): 修复登录验证bug docs(api): 更新API文档 style(code): 格式化代码 refactor(service): 重构用户服务 ``` ## 总结 本代码规范涵盖了Java开发中的主要方面,包括命名规范、代码结构、注释规范、异常处理、日志记录、数据库操作、接口设计、缓存使用、异步处理、单元测试、安全规范和版本控制等。遵循这些规范可以确保代码的质量、可维护性和可扩展性。 遵循这些规范可以确保代码的质量、可维护性和可扩展性,提高团队开发效率。