全局异常捕获处理-@ControllerAdvice+@HandleException

涂涂影院管理系统这个demo中有个异常管理的标签,用于捕获 涂涂影院APP用户异常信息 ,有小伙伴好奇,排除APP,后台端的是如何处理全局异常的,故项目中的实际应用已记之。java

关于目前的异常处理

在使用全局异常处理以前,就目前咱们是如何处理程序中的异常信息的呢?数据库

throws Exception + try-catch微信

怎么讲?app

在咱们目前项目中,每每事务发生在 Service 层,由于会牵扯到调用 Dao 跟数据库打交道,当数据库操做失败时,会让 Service 层抛出运行时异常,Spring 事物管理器就会进行回滚。ui

Service 抛出异常,那么 Controller 必然要去捕获,处理异常,因此,try-catch 就出现了。this

看一下Service:spa

public interface ServiceI{
    ## 保存实体的方法
    public Serializable save(Entity entity) throws Exception;
}

看一下Controller的某个调用方法:设计

@PostMapping(value = "")
public AppResponse add(@RequestBody Entity entity, Errors errors){
    AppResponse resp = new AppResponse();
    try {
        Entity endity = new Entity();
        endity.setXxx();

        ServiceI.save(dog);

        ## 返回数据
        resp.setData(newDog);

    }catch (BusinessException e){
        resp.setFail(e.getMessage());
    }catch (Exception e){
        resp.setFail("操做失败!");
    }
    return resp;
}

看上去也没什么别就,可是一个类中出现大面积的 try-catch ,就显得很是难看且冗余。code

若是使用 @ControllerAdvice + @ExceptionHandler 进行全局的 Controller 层异常处理,只要设计得当,就不再用在 Controller 层进行 try-catch 了。orm

书写全局异常处理

1. @ControllerAdvice注解

定义全局异常处理类,@RestControllerAdvice 为 @ResponseBody + @ControllerAdvice

@Slf4j
@RestControllerAdvice
public class RestCtrlExceptionHandler {

}
2. @ExceptionHandler注解

声明异常处理方法,方法 handleException() 就会处理全部 Controller 层抛出的 Exception 及其子类的异常,这是最基本的用法了。

    @ExceptionHandler(Exception.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result<Object> handleException(Exception e) {

        String errorMsg = "Exception";
        if (e!=null){
            errorMsg = e.getMessage();
            log.error(e.toString());
        }
        return new ResultUtil<>().setErrorMsg(500, errorMsg);
    }

结合上边一、2组合一下:

@Slf4j
@RestControllerAdvice
public class RestCtrlExceptionHandler {

    @ExceptionHandler(TmaxException.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result<Object> handleXCloudException(TmaxException e) {

        String errorMsg = "Tmax exception";
        if (e!=null){
            errorMsg = e.getMsg();
            log.error(e.toString());
        }
        return new ResultUtil<>().setErrorMsg(500, errorMsg);
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(value = HttpStatus.OK)
    public Result<Object> handleException(Exception e) {

        String errorMsg = "Exception";
        if (e!=null){
            errorMsg = e.getMessage();
            log.error(e.toString());
        }
        return new ResultUtil<>().setErrorMsg(500, errorMsg);
    }
}

看一下 handleXCloudException() 方法

一般咱们须要抛出咱们自定义异常,而不是一有异常就所有进入 handleException 中,该方法中 TmaxException 即为咱们自定义的异常。

@Data
public class TmaxException extends RuntimeException {

    private String msg;

    public TmaxException(String msg){
        super(msg);
        this.msg = msg;
    }
}

这样,咱们就能够在 Controller 中抛出咱们定义的异常了,好比:

throw new TmaxException("链接ES失败,请检查ES运行状态");

若是文章有错的地方欢迎指正,你们互相留言交流。习惯在微信看技术文章,想要获取更多的Java资源的同窗,能够关注微信公众号:niceyoo

相关文章
相关标签/搜索