关于SpringMVC中的统一处理异常机制

       在实际Web开发中,我们的dao层、service层是不会处理异常的,因为真正与客户端交流的是controller层,如果我们在dao或service层就把异常处理了,那么我们的客户端是收不到真正的回馈的,可能登录时用户名不存在,或者密码输错了,也没有任何提示或者跳转。那么我们controller层处理异常时,往往需要很多重复繁琐的代码,而且处理异常的逻辑代码要混在控制器层中,高度耦合,不利于我们对代码的重复利用和解耦。

        在SpringMVC中,我们可以利用框架提供的@ControllerAdvice 和 @RestControllerAdvice来自定义处理异常的类。这些类可以方便我们封装自己处理异常的方法和逻辑,并且使他们在项目全域生效。这就很好的解决了我们上面的问题。
        当你在一个类的上方添加了@ControllerAdvice 或 @RestControllerAdvice注解时,就是告诉Spring这是一个统一处理异常的类。在类中我们需要添加处理异常的方法,并在方法上方添加@ExceptionHandler注解。另外在定义处理异常方法时,还要注意几点:

        1.访问权限:应该使用public,只有使用了public才能保证项目全局都能使用

        2.返回值类型:参考处理请求的方法,这里要看实际业务需求我们要返回前端什么样的类型的返回值,一般来说我们会自定义一个返回值类型JsonResult,以便于我们向前端返回自己设定的格式和数据。

        3.方法名称:自定义

        4.参数列表:至少有1个被处理的异常类型参数,可以是任何继承了Throwable的类,可按需添加特定类型的参数,例如HttpServletRequestHttpServletResponse等,但不可以像处理请求的方法那么自由,不能传封装的对象等等。

        5.在同一个项目中,可以有多个统一处理异常的类,每个类中都可以有多个处理异常的方法,只要这些方法处理的异常不完全相同(各方法处理的异常允许存在继承关系)即可。


示例代码:先定一个自定义异常类,作为我们自己service层抛出异常使用

@Getter
public class ServiceException extends RuntimeException {

    private Integer state;

    public ServiceException(Integer state, String message) {
        super(message);
        this.state = state;
    }

}

自定义一个返回值类型类JsonResult 

@Data
public class JsonResult<T> implements Serializable {

    /**
     * 业务状态码
     */
    private Integer state;
    /**
     * 消息
     */
    private String message;
    /**
     * 数据
     */
    private T data;

    public static JsonResult ok() {
        return ok(null);
    }

    public static <T> JsonResult<T> ok(T data) {
        JsonResult jsonResult = new JsonResult();
        jsonResult.setState(ServiceCode.OK);
        jsonResult.setData(data);
        return jsonResult;
    }

    public static JsonResult<Void> fail(ServiceException e) {
        return fail(e.getState(), e.getMessage());
    }

    public static JsonResult<Void> fail(Integer state, String message) {
        JsonResult jsonResult = new JsonResult();
        jsonResult.setState(state);
        jsonResult.setMessage(message);
        return jsonResult;
    }

}

 

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    public GlobalExceptionHandler() {
        log.debug("创建统一处理异常的类:GlobalExceptionHandler");
    }

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

    @ExceptionHandler
    public JsonResult<Void> handleBindException(BindException e) {
        log.debug("处理BindException:{}", e.getMessage());

        StringBuilder stringBuilder = new StringBuilder();
        List<FieldError> fieldErrors = e.getFieldErrors();
        for (FieldError fieldError : fieldErrors) {
            String message = fieldError.getDefaultMessage();
            stringBuilder.append(message);
        }

        return JsonResult.fail(ServiceCode.ERR_BAD_REQUEST, stringBuilder.toString());
    }

    @ExceptionHandler
    public JsonResult<Void> handleThrowable(Throwable e) {
        log.debug("处理Throwable");
        e.printStackTrace();
        String message = "程序运行过程中出现意外错误,请联系系统管理员!";
        return JsonResult.fail(ServiceCode.ERR_INTERNAL_SERVER_ERROR, message);
    }

}

        最后这个处理Throwable的异常算是兜底异常,当控制台出现这样的异常提示时,我们就要注意,程序出现了我们未曾处理过的异常。就要注意了。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Leon_coding

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

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

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

打赏作者

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

抵扣说明:

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

余额充值