SpringBoot入门-统一异常处理

本文围绕Java项目开发中的异常处理展开。介绍了通用异常处理,利用SpringBoot的@ControllerAdvice和@ExceptionHandler注解处理所有异常,将详细信息写入日志,给用户简单提示。还阐述了业务异常处理,以登录功能为例,引入业务异常类解决正常与异常流程未分离及事务回退问题。

在项目的开发和调试中,错误难免发生。在java中这种程序错误就叫做异常,如果程序出现异常,会是什么样子呢。看下图

 这种异常展现方式有很多问题,首先对用户很不友好,而且里面包含了栈信息,造成安全隐患,同时对于前端小伙伴对接也会造成不便。

通用异常处理

java中所有异常的基类是Exception类,处理好这个类就能处理所有异常了

SpringBoot为我们提供了@ControllerAdvice注解来处理异常

@ControllerAdvice
public class ExceptionControllerAdvice extends BaseController {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result exceptionHandler(Exception ex) {
        logger.error("服务器异常: {}", ex);
        return resultFail("服务器出错了,请稍后再试");
    }

@ExceptionHandler注解用来标识这个方法处理的异常,我们只需要把异常的详细信息写入日志系统,返回用户简单的错误提示就行了,错误码是0,这样也方便前端小伙伴做统一的错误提示

 业务异常处理

先看一个简单的需求,登录功能。登录成功返回token,失败返回账号错误的提示信息。看看service层的实现

public String login(String name, String password) {
    if ("cloud".equals(name) && "123".equals(password)) {
        String token = "token";
        return token;
    } else {
        return "";
    }
}

登录成功返回token,失败返回空字符串。controller层通过判断login方法的返回值是否为空来决定是返回token还是返回错误信息。

 @GetMapping("/login")
public Result login(String name, String password) {
    String token = userService.login(name, password);
    if (StringUtils.isEmpty(token)) {
        return resultFail("账户错误");
    } else {
        return resultOk(token);
    }
}

但这种实现方式有很多不好的地方,首先是正常流程和异常流程没有分离,其实调用者只关心正常流程,其次这种方式没法让事务回退,比如我在登陆方法里记录了一些信息,但登陆失败后这些信息是不需要的,需要回退。如何解决呢?我们可以通过引入业务异常类来解决。

public class ServiceFailException extends RuntimeException

新建一个异常类,继承自RuntimeException,这样就不需要强制用try catch捕获异常

改写login方法

public String login(String name, String password) {
    if ("cloud".equals(name) && "123".equals(password)) {
        String token = "token";
        return token;
    }
    throw new ServiceFailException("账号错误");
}

改写controller方法

@GetMapping("/login")
public Result login(String name, String password) {
    return resultOk(userService.login(name, password));
}

可以看到调用方只需要考虑正常流程,变的异常简洁

在ControllerExceptionAdvice类下面处理该自定义异常

@ResponseBody
@ExceptionHandler(value = ServiceFailException.class)
public Result serviceFailHandler(ServiceFailException ex) {
    logger.error("service层异常: {}", ex);
    return resultFail(ex.getStatus(), ex.getMessage());
}

错误信息展示

参考项目(模块: SpringBoot-HelloWorld): https://gitee.com/huatin/java-test 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值