关于处理异常

在Java语言中,异常的体系结构大致是:

Throwable
-- Error
-- -- OutOfMemoryError(OOM)
-- Exception
-- -- IOException
-- -- RuntimeException
-- -- -- NullPointerException(NPE)
-- -- -- ClassCastException
-- -- -- IndexOutOfBoundsException
-- -- -- -- ArrayIndexOutOfBoundsException
-- -- -- -- StringIndexOutOfBoundsException

如果调用的方法抛出了“非RuntimeException”,则必须:

  • 当前方法声明抛出此异常
  • 使用try...catch代码块包裹此方法的调整代码
    • 真正意义上的“处理了异常”

关于“处理异常”,需要明确的告诉用户“这次操作失败了,失败的原因是XXXXX,你可以通过XXXXX再次尝试,并避免出现此类错误”!

所以,在整个项目,只有Controller才是适合且必须处理异常的组件,因为它可以将错误的描述文本响应到客户端去,而项目中的其它组件(例如Service等)不适合且不应该处理异常,因为它们不可以直接与客户端进行交互,且如果它们处理了异常,则Controller在调用时将无法知道曾经出现过异常,更加无法处理!

在使用Spring MVC框架时,控制器(Controller)可以不处理异常(如果执行过程中出现异常,则自动抛出),框架提供了统一处理异常的机制。

关于统一处理异常:

  • 统一处理异常的代码应该编写在专门的类中,并且,在此类上添加@ControllerAdvice / @RestControllerAdvice注解

    • @ControllerAdvice / @RestControllerAdvice注解的类中的特定方法将作用于每一次处理请求的过程中
    • 其实,统一处理异常的代码可以写在某个控制器中,但是,将只能作用于此控制器中各处理请求的方法,无法作用于其它控制器中处理请求的方法
  • 在类中自定义方法来处理异常

    • 注解:@ExceptionHandler
    • 访问权限:应该public
    • 返回值类型:设计原则可参考控制器中处理请求的方法
    • 方法名称:自定义
    • 参数列表:必须包含异常类型的参数,且此参数就是Spring MVC框架调用控制器方法时捕获的异常,另外,可按需添加HttpServerRequestHttpServletResponse等少量限定类型的参数

在同一个项目中,可以有多个以上处理异常的类,或同一个处理异常的类中可以有多个处理异常的方法,只要这些方法处理的异常不冲突即可!并且,这些方法处理的异常允许存在父子级继承关系,例如某个方法处理ServiceException,另一个方法处理RuntimeException,当出现ServiceException,仍会按照处理ServiceException的方法进行处理!

强烈建议在每个项目中都添加一个处理Throwable的方法,避免项目出现500错误!例如:

package cn.tedu.csmall.product.handler;

import cn.tedu.csmall.product.ex.ServiceException;
import cn.tedu.csmall.product.web.JsonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler
    public JsonResult<Void> handleServiceException(ServiceException e) {
        log.debug("处理ServiceException,serviceCode={},message={}", e.getServiceCode(), e.getMessage());
        return JsonResult.fail(e);
    }

    @ExceptionHandler
    public JsonResult<Void> handleThrowable(Throwable e) {
        log.debug("处理Throwable");
        e.printStackTrace();

        Integer serviceCode = 99999;
        String message = "程序运行过程中出现未知错误,请联系系统管理员!";
        return JsonResult.fail(serviceCode, message);
    }

}

注意:以上处理Throwable的方法,并不是真正意义的“处理”了异常,在此方法中,应该通过日志输出异常的详情信息,并且,在后续出现相关异常时,在此类中补充针对这些异常的精准处理!

另外,在@ExceptionHandler中,可以配置异常类型的参数,此参数是异常类型的数组,用于指定需要处理哪些种类的异常,但是,通常并不需要进行此项配置,因为方法的参数就可以直接表示处理哪种异常!此注解参数大多应用于“多种不相关的异常使用同一种处理方式”的情景!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香扑扑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值