当前位置: 首页 > news >正文

Java异常处理与全局异常处理全面指南

Java异常处理与全局异常处理全面指南

一、Java异常处理基础

1. 异常分类

Java中的异常分为两大类:

  • Checked Exception(检查型异常):必须被捕获或声明抛出,如IOException、SQLException
  • Unchecked Exception(非检查型异常):RuntimeException及其子类,如NullPointerException、ArrayIndexOutOfBoundsException

2. 基本异常处理语法

try {
    // 可能抛出异常的代码
} catch (SpecificException e) {
    // 处理特定异常
} catch (GeneralException e) {
    // 处理更一般的异常
} finally {
    // 无论是否发生异常都会执行的代码
}

3. 异常处理最佳实践

  1. 不要忽略异常:空的catch块是"罪恶"的
  2. 优先处理最具体的异常
  3. 合理使用finally释放资源
  4. 考虑使用try-with-resources(Java 7+)
  5. 避免在finally块中使用return

二、Spring全局异常处理机制

1. @ControllerAdvice + @ExceptionHandler

@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {
        ErrorResponse error = new ErrorResponse(
            "SERVER_ERROR", 
            "An unexpected error occurred",
            HttpStatus.INTERNAL_SERVER_ERROR.value()
        );
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
    
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleResourceNotFound(
        ResourceNotFoundException ex) {
        ErrorResponse error = new ErrorResponse(
            "NOT_FOUND", 
            ex.getMessage(),
            HttpStatus.NOT_FOUND.value()
        );
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }
}

2. 自定义异常类

public class BusinessException extends RuntimeException {
    private String errorCode;
    private HttpStatus httpStatus;
    
    public BusinessException(String message, String errorCode, HttpStatus httpStatus) {
        super(message);
        this.errorCode = errorCode;
        this.httpStatus = httpStatus;
    }
    
    // getters
}

3. 统一响应格式

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ErrorResponse {
    private String errorCode;
    private String message;
    private int status;
    private long timestamp;
    private String path;
    private List<ValidationError> validationErrors;
    
    public ErrorResponse(String errorCode, String message, int status) {
        this.errorCode = errorCode;
        this.message = message;
        this.status = status;
        this.timestamp = System.currentTimeMillis();
    }
}

@Data
@AllArgsConstructor
public class ValidationError {
    private String field;
    private String message;
}

三、高级异常处理技巧

1. 处理验证异常(Validation)

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationExceptions(
    MethodArgumentNotValidException ex) {
    
    List<ValidationError> errors = ex.getBindingResult()
        .getFieldErrors()
        .stream()
        .map(error -> new ValidationError(
            error.getField(), 
            error.getDefaultMessage()))
        .collect(Collectors.toList());
    
    ErrorResponse error = new ErrorResponse(
        "VALIDATION_FAILED",
        "Validation failed for one or more fields",
        HttpStatus.BAD_REQUEST.value(),
        errors
    );
    
    return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}

2. 国际化异常消息

@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(
    BusinessException ex, 
    WebRequest request,
    Locale locale) {
    
    String message = messageSource.getMessage(
        ex.getMessageKey(), 
        ex.getArgs(), 
        locale);
    
    ErrorResponse error = new ErrorResponse(
        ex.getErrorCode(),
        message,
        ex.getHttpStatus().value()
    );
    
    return new ResponseEntity<>(error, ex.getHttpStatus());
}

3. 日志记录策略

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex, WebRequest request) {
    logger.error("Unexpected error occurred: {}", ex.getMessage(), ex);
    
    ErrorResponse error = new ErrorResponse(
        "SERVER_ERROR",
        "An unexpected error occurred",
        HttpStatus.INTERNAL_SERVER_ERROR.value(),
        request.getDescription(false)
    );
    
    return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}

四、实战建议

  1. 分层异常处理

    • 控制器层:处理HTTP相关异常
    • 服务层:处理业务逻辑异常
    • 数据访问层:处理数据相关异常
  2. 异常转换:将底层异常转换为上层业务异常

  3. 异常信息设计

    • 包含足够的信息用于调试
    • 不暴露敏感信息
    • 提供明确的错误代码
  4. 监控与报警:对关键异常设置监控报警

  5. 文档化:为API消费者提供清晰的错误代码和含义文档

五、常见问题解决方案

  1. 处理404错误
@ControllerAdvice
public class CustomErrorController implements ErrorController {
    
    @RequestMapping("/error")
    public ResponseEntity<ErrorResponse> handleError(HttpServletRequest request) {
        Integer status = (Integer) request.getAttribute("javax.servlet.error.status_code");
        Exception exception = (Exception) request.getAttribute("javax.servlet.error.exception");
        
        ErrorResponse error = new ErrorResponse(
            "NOT_FOUND",
            "Requested resource not found",
            status
        );
        
        return new ResponseEntity<>(error, HttpStatus.valueOf(status));
    }
}
  1. 处理跨域异常
@ExceptionHandler
public ResponseEntity<ErrorResponse> handleCorsException(CorsException ex) {
    ErrorResponse error = new ErrorResponse(
        "CORS_ERROR",
        ex.getMessage(),
        HttpStatus.FORBIDDEN.value()
    );
    return new ResponseEntity<>(error, HttpStatus.FORBIDDEN);
}
  1. 处理文件上传大小限制异常
@ExceptionHandler(MaxUploadSizeExceededException.class)
public ResponseEntity<ErrorResponse> handleMaxSizeException(
    MaxUploadSizeExceededException exc) {
    
    ErrorResponse error = new ErrorResponse(
        "FILE_TOO_LARGE",
        "File size exceeds the allowed limit",
        HttpStatus.BAD_REQUEST.value()
    );
    
    return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}

六、总结

良好的异常处理是构建健壮Java应用程序的关键。通过合理使用Java原生异常机制和Spring的全局异常处理功能,可以:

  1. 提高代码的健壮性和可维护性
  2. 提供一致的用户体验
  3. 便于问题排查和调试
  4. 实现更好的系统监控

记住:异常处理的目标不是消灭所有异常,而是以可控的方式处理异常,并提供有意义的反馈。

http://www.dtcms.com/a/112841.html

相关文章:

  • 3-Visual Studio 2022打包NET开发项目为安装包
  • 手部穴位检测技术:基于OpenCV和MediaPipe的实现
  • C++/Qt 模拟sensornetwork的工作
  • 定积分的应用(4.39-4.48)
  • 【Game】Powerful——Riding Animals(5)
  • 【Scrapy】Scrapy教程10——CSS选择器详解
  • 第十二届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组
  • SQL BETWEEN 语句详解
  • 【寻找Linux的奥秘】第三章:基础开发工具(上)
  • FPGA入门学习Day0——状态机相关内容解析HDLbits练习
  • 爬虫自动化工具:DrissionPage
  • VLAN详解
  • #SVA语法滴水穿石# (000)断言基本概念和背景
  • 第1课:React开发环境搭建与第一个组件
  • 设计模式简述(二)单例模式
  • Turnitin论文查重检测注意事项有哪些?
  • Centos7上安装docker - yum在线的方式
  • Kafka 如何解决消息堆积问题?
  • 软件工程面试题(二十九)
  • Kafka Consumer Group
  • Python-文件操作
  • Photoshop 2025 Mac中文Ps图像编辑
  • Python3 学习笔记
  • 《AI大模型趣味实战》智能财务助手系统架构设计
  • PE结构(十五)系统调用与函数地址动态寻找
  • 技术驱动革新,强力巨彩LED软模组助力创意显示
  • 搭建K8S-1.23
  • P1577 切绳子(二分)
  • tomcat与spring-web
  • 智能工厂的数字孪生与信息物理系统架构研究