生产项目中的异常处理(ExceptionHandler)

在实际编码工作中,对异常的处理往往是复杂繁琐的,在java中到底有哪些异常,生产环境下又是如何处理的呢?

一.异常分类 

在 Java 中所有异常类型都是内置类 java.lang.Throwable 类的子类,即 Throwable 位于异常类层次结构的顶层。Throwable 类是所有异常和错误的父类,下面有 Error 和 Exception 两个子类分别表示错误和异常。

Error 定义了在通常环境下不希望被程序捕获的异常。 

Error 类型的异常用于 Java 运行时由系统显示与运行时系统本身有关的错误。堆栈溢出是这种错误的一例(递归代码设计不严谨便会出现这种问题)。这种异常通常是jvm级别的问题,它们通常是灾难性的致命错误,不是程序可以控制的,所以一般面对这种问题需要重构代码结构,而不是通过异常处理解决。

Exception 类用于用户程序可能出现的异常情况,它也是用来创建自定义异常类型类的类。Exception 则分为运行时异常(RuntimeException)和非运行时异常(OtherException),这两种异常有很大的区别,也称为不检查异常(Unchecked Exception)和检查异常(CheckedException)。

运行时异常都是 RuntimeException 类及其子类异常,如 NullPointerException、IndexOutOfBoundsException 等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般由程序逻辑错误引起,程序应该从逻辑角度尽可能避免这类异常的发生。 

非运行时异常是指 RuntimeException 以外的异常,类型上都属于 Exception 类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如 IOException、ClassNotFoundException 等以及用户自定义的 Exception 异常,一般情况下不自定义检查异常。 

二.异常处理

在 Java 中,捕获异常的基本语法是 try-catch-finally 块。try 块用于包含可能会抛出异常的代码块,catch 块用于捕获并处理异常,finally 块用于清理资源 。在 try 块中,我们可以放入需要检查的代码。如果这些代码抛出了异常,那么就会跳转到对应的 catch 块中,进行异常处理的相关操作。同时,不论是否抛出异常,finally 块中的代码都会被执行。

try {
    // 可能会抛出异常的代码
} catch (Exception e) {
    // 捕获并处理异常
} finally {
    // 清理资源
}

 另外,Java 还提供了一种带有异常声明的特殊类型的语法,称为 throw 语法。通过 throw 语法,我们可以在程序中主动抛出一个异常。在项目中,异常如果需要在上层处理的话,则会用到throw。

三.异常统一处理(ExceptionHandler)

在实际生产项目中,不同的异常情况往往设计好了不同的响应码(比如下面的例子)

微服务中使用共通异常处理:任何API产生异常都会在异常类(ExceptipnHandler)中处理。为了实现共通的处理需要使用在共通处理类中使用@ControllerAdvice,这个注解是Spring3.2提供的新注解,它是一个Controller增强器,可对controller中被 @RequestMapping注解的方法加一些逻辑处理。最常用的就是异常处理统一异常处理,需要配合@ExceptionHandler使用。同时,需要使用共通异常处理的controller也要用@Validated注解标记才能实现这个功能。当将异常抛到controller时, 可以对异常进行统一处理,规定返回的格式。

例如为了处理以下异常

HttpMessageNotReadableException  请求体无法被转换为控制器方法所需的对象,json反序列化失败,或json为空。

MethodArgumentTypeMismatchException  请求参数的类型与方法参数类型不一致,提交的表单数据与Controller方法的参数类型不匹配。

MissingRequestHeaderException  请求中缺少必需的头部信息,@RequestHeader中required属性为true,但实际请求中却没有包含该头部信息

MethodArgumentNotValidException和ConstraintViolationException都是用来处理使用注解

@Valid时出现的问题。
将请求体解析并绑定到 java bean 时,如果出错,则抛出 MethodArgumentNotValidException 异常,如@RequestBody
普通参数(非 java bean)校验出错时,会抛出 ConstraintViolationException 异常,如@RequestParam,@RequestHeader

会做如下处理

 @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Response> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
    
        logger.info("Invalid arguments found : " + ex.getMessage());
        // Get the error messages for invalid fields
        List<FieldError> errors = ex.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(fieldError -> new FieldError(fieldError.getField(), fieldError.getDefaultMessage()))
                .collect(Collectors.toList());
    
        String message = messageSource.getMessage("invalid.data.message", null, LocaleContextHolder.getLocale());
        Response response = new Response(false, message)
                .setErrors(errors);
        ResponseEntity<Response> responseEntity = ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
        return responseEntity;
    }

 

  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值