20 KiB
20 KiB
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 正确的导入方式
// ✅ 正确示例:使用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<UserResponse> createUser(@RequestBody CreateUserRequest request) {
UserResponse response = userService.createUser(request);
return Result.success(response);
}
}
2.1.2 错误的导入方式
// ❌ 错误示例:在代码中使用全路径限定名
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<com.emotionmuseum.dto.response.UserResponse>
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 导入顺序规范
// 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 导入优化规范
// ✅ 推荐:使用通配符导入相关的类
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 静态导入规范
// ✅ 正确:静态导入常用的静态方法
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 导入冲突处理
// 当出现类名冲突时,使用import别名或明确指定包名
import com.emotionmuseum.dto.response.Result;
import org.springframework.http.ResponseEntity;
public class UserController {
// 使用别名避免冲突
public com.emotionmuseum.dto.response.Result<UserResponse> createUser() {
// 业务逻辑
}
// 或者使用import别名(如果IDE支持)
// import com.emotionmuseum.dto.response.Result as EmotionResult;
}
3. 代码结构规范
3.1 类结构顺序
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 方法结构
public Result<UserResponse> 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 类注释
/**
* 用户控制器
*
* @author 作者名
* @since 1.0.0
*/
@RestController
public class UserController {
}
4.2 方法注释
/**
* 根据用户ID获取用户信息
*
* @param userId 用户ID
* @return 用户信息响应对象
* @throws UserNotFoundException 当用户不存在时抛出
*/
public Result<UserResponse> getUserById(Long userId) {
}
5. 异常处理规范
5.1 异常定义
public class UserNotFoundException extends BusinessException {
public UserNotFoundException(String message) {
super(message);
}
}
5.2 异常抛出
if (user == null) {
throw new UserNotFoundException("用户不存在,ID: " + userId);
}
6. Log4j2日志规范
6.1 日志级别使用
// 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 日志记录规范
// 使用占位符,避免字符串拼接
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日志追踪
// 设置MDC信息
MDC.put("userId", userId.toString());
MDC.put("requestId", UUID.randomUUID().toString());
try {
// 业务逻辑
} finally {
// 清理MDC
MDC.clear();
}
7. 数据库操作规范
7.1 MyBatis-Plus使用
// 查询单个
User user = userMapper.selectById(userId);
// 条件查询
List<User> users = userMapper.selectList(
new LambdaQueryWrapper<User>()
.eq(User::getStatus, UserStatus.ACTIVE)
.orderByDesc(User::getCreateTime)
);
8. 接口设计规范
8.1 Controller层规范
重要原则:Controller层只负责接收请求、参数校验、调用Service层、返回结果,严禁在Controller层编写任何业务逻辑代码。
@RestController
@RequestMapping("/api/users")
@Validated
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public Result<UserResponse> createUser(@Valid @RequestBody CreateUserRequest request) {
// Controller层只做:参数校验(通过@Valid)、调用Service、返回结果
UserResponse response = userService.createUser(request);
return Result.success(response);
}
@GetMapping("/{id}")
public Result<UserResponse> getUserById(@PathVariable Long id) {
// Controller层只做:调用Service、返回结果
UserResponse response = userService.getUserById(id);
return Result.success(response);
}
@PutMapping("/{id}")
public Result<UserResponse> updateUser(@PathVariable Long id,
@Valid @RequestBody UpdateUserRequest request) {
// Controller层只做:参数校验、调用Service、返回结果
UserResponse response = userService.updateUser(id, request);
return Result.success(response);
}
@DeleteMapping("/{id}")
public Result<Void> deleteUser(@PathVariable Long id) {
// Controller层只做:调用Service、返回结果
userService.deleteUser(id);
return Result.success(null);
}
}
8.2 Controller层禁止事项
// ❌ 错误示例:在Controller层编写业务逻辑
@PostMapping("/users")
public Result<UserResponse> 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<UserResponse> createUser(@Valid @RequestBody CreateUserRequest request) {
UserResponse response = userService.createUser(request);
return Result.success(response);
}
8.3 请求响应对象规范
@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层完成,包括数据校验、业务规则判断、数据处理、事务管理等。
@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缓存注解
@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 异步方法定义
@Async("notificationExecutor")
public CompletableFuture<Void> 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 测试类结构
@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 安全注解使用
@RestController
@RequestMapping("/api/users")
public class UserController {
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin")
public Result<List<UserResponse>> getAllUsers() {
// 只有ADMIN角色可以访问
}
@PreAuthorize("hasRole('USER') and #userId == authentication.principal.id")
@GetMapping("/{userId}")
public Result<UserResponse> getUserById(@PathVariable Long userId) {
// 只有USER角色且只能访问自己的信息
}
@PreAuthorize("permitAll()")
@PostMapping("/register")
public Result<UserResponse> register(@Valid @RequestBody CreateUserRequest request) {
// 允许所有人访问
}
}
12.2 输入验证
@PostMapping("/users")
public Result<UserResponse> createUser(@Valid @RequestBody CreateUserRequest request) {
return userService.createUser(request);
}
12.3 敏感信息处理
// 日志中脱敏
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 密码处理规范
@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处理
@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提交规范
feat(user): 添加用户注册功能
fix(auth): 修复登录验证bug
docs(api): 更新API文档
style(code): 格式化代码
refactor(service): 重构用户服务
总结
本代码规范涵盖了Java开发中的主要方面,包括命名规范、代码结构、注释规范、异常处理、日志记录、数据库操作、接口设计、缓存使用、异步处理、单元测试、安全规范和版本控制等。遵循这些规范可以确保代码的质量、可维护性和可扩展性。 遵循这些规范可以确保代码的质量、可维护性和可扩展性,提高团队开发效率。