Java异常处理流程如何规整

wen java案例 25

本文目录导读:

Java异常处理流程如何规整

  1. 异常处理的核心原则
  2. 标准异常处理模式
  3. 自定义异常体系
  4. 统一异常处理
  5. 资源管理最佳实践
  6. 异常日志规范
  7. 最佳实践总结

我来系统地介绍Java异常处理的规范化流程和最佳实践。

异常处理的核心原则

异常分类

// Throwable 体系
Throwable
├── Error(不可处理,系统级错误)
│   ├── OutOfMemoryError
│   └── StackOverflowError
└── Exception(可处理)
    ├── Checked Exception(必须处理)
    │   ├── IOException
    │   ├── SQLException
    │   └── ClassNotFoundException
    └── Unchecked Exception(运行时异常)
        ├── NullPointerException
        ├── IllegalArgumentException
        └── IndexOutOfBoundsException

标准异常处理模式

基础try-catch-finally

public class StandardExceptionHandling {
    // 基本模式
    public void basicHandling() {
        try {
            // 可能抛出异常的代码
            riskyOperation();
        } catch (SpecificException e) {
            // 处理特定异常
            log.error("特定异常发生", e);
            throw new BusinessException("操作失败", e);
        } catch (GeneralException e) {
            // 处理通用异常
            log.error("通用异常", e);
            handleGracefully(e);
        } finally {
            // 清理资源(必须执行)
            closeResources();
        }
    }
    // Java 7+ try-with-resources
    public void tryWithResources() {
        try (Connection conn = getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT * FROM users")) {
            while (rs.next()) {
                processUser(rs);
            }
        } catch (SQLException e) {
            log.error("数据库操作异常", e);
            throw new DataAccessException("查询用户失败", e);
        }
    }
}

多层异常处理

public class MultiLayerExceptionHandling {
    // Service层
    public class UserService {
        public User createUser(UserDTO dto) {
            try {
                validateUser(dto);
                User user = convertToEntity(dto);
                return userRepository.save(user);
            } catch (ValidationException e) {
                throw new BusinessException("用户数据验证失败", e);
            } catch (DataAccessException e) {
                throw new BusinessException("用户创建失败", e);
            }
        }
    }
    // Controller层
    @RestController
    public class UserController {
        @PostMapping("/users")
        public ResponseEntity<ApiResponse<User>> createUser(@RequestBody UserDTO dto) {
            try {
                User user = userService.createUser(dto);
                return ResponseEntity.ok(ApiResponse.success(user));
            } catch (BusinessException e) {
                return ResponseEntity.badRequest()
                    .body(ApiResponse.error(e.getMessage()));
            } catch (Exception e) {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error("系统异常"));
            }
        }
    }
}

自定义异常体系

异常层次结构

// 基础业务异常
public abstract class BaseException extends RuntimeException {
    private final String errorCode;
    private final Object[] args;
    public BaseException(String errorCode, String message, Object... args) {
        super(message);
        this.errorCode = errorCode;
        this.args = args;
    }
    public BaseException(String errorCode, String message, Throwable cause) {
        super(message, cause);
        this.errorCode = errorCode;
        this.args = new Object[0];
    }
    public String getErrorCode() {
        return errorCode;
    }
    public Object[] getArgs() {
        return args;
    }
}
// 具体业务异常
public class UserNotFoundException extends BaseException {
    public UserNotFoundException(Long userId) {
        super("USER_001", 
              String.format("用户不存在: %d", userId), 
              userId);
    }
}
public class InsufficientBalanceException extends BaseException {
    public InsufficientBalanceException(Double balance, Double required) {
        super("BALANCE_001", 
              String.format("余额不足: 当前%.2f, 需要%.2f", balance, required),
              balance, required);
    }
}

异常码枚举

public enum ErrorCode {
    // 系统级错误
    SYSTEM_ERROR("SYS_001", "系统异常"),
    DATABASE_ERROR("SYS_002", "数据库异常"),
    // 业务级错误
    USER_NOT_FOUND("USER_001", "用户不存在"),
    USER_ALREADY_EXISTS("USER_002", "用户已存在"),
    INVALID_PARAMETER("PARAM_001", "参数验证失败"),
    // 权限错误
    UNAUTHORIZED("AUTH_001", "未授权"),
    FORBIDDEN("AUTH_002", "无权限"),
    TOKEN_EXPIRED("AUTH_003", "Token过期");
    private final String code;
    private final String message;
    ErrorCode(String code, String message) {
        this.code = code;
        this.message = message;
    }
    public String getCode() { return code; }
    public String getMessage() { return message; }
}

统一异常处理

Spring Boot全局异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
        ErrorResponse response = ErrorResponse.builder()
            .code(e.getErrorCode())
            .message(e.getMessage())
            .timestamp(LocalDateTime.now())
            .build();
        return ResponseEntity.badRequest().body(response);
    }
    @ExceptionHandler(ValidationException.class)
    public ResponseEntity<ErrorResponse> handleValidationException(ValidationException e) {
        ErrorResponse response = ErrorResponse.builder()
            .code("VALIDATION_ERROR")
            .message("参数验证失败")
            .errors(e.getErrors())
            .timestamp(LocalDateTime.now())
            .build();
        return ResponseEntity.badRequest().body(response);
    }
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleException(Exception e) {
        log.error("未处理的异常", e);
        ErrorResponse response = ErrorResponse.builder()
            .code("SYSTEM_ERROR")
            .message("系统异常,请联系管理员")
            .timestamp(LocalDateTime.now())
            .build();
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
            .body(response);
    }
    // 参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationExceptions(
            MethodArgumentNotValidException ex) {
        List<String> errors = ex.getBindingResult()
            .getFieldErrors()
            .stream()
            .map(error -> error.getField() + ": " + error.getDefaultMessage())
            .collect(Collectors.toList());
        ErrorResponse response = ErrorResponse.builder()
            .code("VALIDATION_ERROR")
            .message("参数验证失败")
            .errors(errors)
            .timestamp(LocalDateTime.now())
            .build();
        return ResponseEntity.badRequest().body(response);
    }
}
@Builder
@Data
public class ErrorResponse {
    private String code;
    private String message;
    private List<String> errors;
    private LocalDateTime timestamp;
}

资源管理最佳实践

使用try-with-resources

public class ResourceManagement {
    // 自动关闭资源
    public void processFile(String path) {
        try (FileInputStream fis = new FileInputStream(path);
             BufferedReader reader = new BufferedReader(new InputStreamReader(fis))) {
            String line;
            while ((line = reader.readLine()) != null) {
                processLine(line);
            }
        } catch (IOException e) {
            log.error("文件处理异常", e);
            throw new FileProcessingException("处理文件失败: " + path, e);
        }
    }
    // 自定义资源
    public class DatabaseResource implements AutoCloseable {
        private Connection connection;
        public DatabaseResource(Connection connection) {
            this.connection = connection;
        }
        @Override
        public void close() {
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    log.error("关闭数据库连接失败", e);
                }
            }
        }
    }
}

异常日志规范

统一的日志记录

public class ExceptionLogging {
    private static final Logger log = LoggerFactory.getLogger(ExceptionLogging.class);
    public void handleWithLogging() {
        try {
            riskyOperation();
        } catch (BusinessException e) {
            // 记录业务异常
            log.warn("业务异常: code={}, message={}, args={}", 
                    e.getErrorCode(), e.getMessage(), e.getArgs());
            // 重新包装后抛出
            throw new ServiceException("处理失败", e);
        } catch (DataAccessException e) {
            // 记录数据访问异常(包含堆栈信息)
            log.error("数据访问异常: {}", e.getMessage(), e);
            // 转换为业务异常
            throw new ServiceException("数据操作失败", e);
        } catch (Exception e) {
            // 记录未知异常
            log.error("未预期的异常", e);
            // 抛出系统异常
            throw new SystemException("系统异常", e);
        }
    }
    // 异常信息记录工具
    public static String buildErrorMessage(Exception e) {
        StringBuilder sb = new StringBuilder();
        sb.append("异常类型: ").append(e.getClass().getName());
        sb.append(", 消息: ").append(e.getMessage());
        if (e.getCause() != null) {
            sb.append(", 原因: ").append(e.getCause().getMessage());
        }
        // 添加业务上下文
        sb.append(", 时间: ").append(LocalDateTime.now());
        sb.append(", 线程: ").append(Thread.currentThread().getName());
        return sb.toString();
    }
}

最佳实践总结

异常处理原则

public class ExceptionBestPractices {
    // ✅ 正确:使用具体的异常类型
    public void specificException() {
        try {
            processStream(inputStream);
        } catch (IOException e) {
            throw new BusinessException("流处理失败", e);
        }
    }
    // ❌ 错误:捕获过于宽泛的异常
    public void broadException() {
        try {
            processStream(inputStream);
        } catch (Exception e) {  // 太过宽泛
            throw new BusinessException("处理失败", e);
        }
    }
    // ✅ 正确:异常转换时保留原始异常
    public void preserveCause() {
        try {
            databaseOperation();
        } catch (SQLException e) {
            throw new BusinessException("数据库操作失败", e);  // 保留cause
        }
    }
    // ❌ 错误:丢弃原始异常信息
    public void loseCause() {
        try {
            databaseOperation();
        } catch (SQLException e) {
            throw new BusinessException("数据库操作失败");  // 丢失原始异常
        }
    }
}

异常处理检查清单

  • [x] 是否使用了具体的异常类型?
  • [x] 自定义异常是否继承自合适的父类?
  • [x] 异常信息是否包含足够的上下文?
  • [x] 是否保留了原始异常堆栈?
  • [x] 资源是否正确关闭(try-with-resources)?
  • [x] 是否避免在finally中抛出异常?
  • [x] 异常日志是否包含关键信息?
  • [x] 是否实现了统一异常处理?

这样的异常处理架构能够保证代码的健壮性、可维护性和可读性,同时提供了清晰的错误反馈给调用方。

抱歉,评论功能暂时关闭!