前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Boot 快速入门系列(VII)—— 全局异常处理篇

Spring Boot 快速入门系列(VII)—— 全局异常处理篇

作者头像
IT技术小咖
修改2019-10-21 13:34:51
4320
修改2019-10-21 13:34:51
举报
文章被收录于专栏:码上修行码上修行

前言

《Spring Boot 快速入门系列》上一节「接口规范篇」讲完了,小伙伴们是否已经掌握了基本的接口编写规范(后面会有一篇专门演示在线接口文档内容)。

Spring Boot 快速入门系列:

Spring Boot 快速入门系列(先导篇) —— 从 Hello World 开始

Spring Boot 快速入门系列(I) —— 属性配置篇

Spring Boot 快速入门系列(II)—— 数据操作篇之 Spring Data JPA

Spring Boot 快速入门系列(III)—— 数据操作篇之 JdbcTemplate Spring Boot 快速入门系列(IV)—— 数据操作篇之 MyBatis

Spring Boot 快速入门系列(V)—— 事务管理篇之 @Transactional

Spring Boot 快速入门系列(VI)—— 接口规范篇

对于一个接口服务来说,异常处理显得尤为重要,因为没有任何程序是没有 bug 的。那么在程序可能出现异常的地方,需要我们手动捕获和处理异常。比如像下面这 3 种方式见的很多:

代码语言:javascript
复制
try {    
    // 可能发生异常的逻辑    
    ...    
    doSomething(); 
} catch (ExceptionType e) {    
    // 异常处理    
    logger.error(e);    
    throw new MyException(e.getMessage());
}
// or
try {    
    // 可能发生异常的逻辑    
    ...    
    doSomething(); 
} catch (ExceptionType1 e1) {    
    // 异常处理    
    logger.error(e1);    
    throw new MyException(e1.getMessage());
} catch (ExceptionType2 e2) {    
    // 异常处理    
    logger.error(e2);    
    throw new MyException(e2.getMessage());
}
// or
try {    
    // 可能发生异常的逻辑    
    ...    
    doSomething(); 
} catch (ExceptionType1 e1 | ExceptionType2 e2) {    
    // 异常处理    
    logger.error(e1 + "\n" + e2);    
    throw new MyException(e1.getMessage() + e2.getMessage());
}

像这种标准的 try { ... } catch(ExceptionTypes e) { ... } 是处理异常的常见解决问题的方式,但是实际程序我们不可能每一段代码都会 try-catch 处理,还有一些异常可能无法提前预知,没有显式的捕获处理,那如果此时程序发生异常,我们该如何处理呢。

那么今天我们就来讲讲对于基于 Spring Boot 构建的项目中如何处理这些异常问题的。

异常处理

1. @ExceptionHandler 注解

了解 SpringMVC 或 Spring Boot 框架的人应该知道 @ExceptionHandler 这个异常处理注解,我们可以使用这个注解来捕获程序异常。

1.1 单一 Action/Controller 异常处理

这种使用 @ExceptionHandler 注解的场景较少,但作为学习异常处理还是非常不错的,只需在对应的 xxxAction / xxxController 控制层增加一个异常处理的方法,并使用 @ExceptionHandler 注解标识即可。

代码语言:javascript
复制
@ExceptionHandler(Exception.class)
public ResponseDataVO handleException() {    
    // 统一返回数据格式:《Spring Boot 快速入门之参数规范篇》的示例代码  
    // 以下相同  
    return new ResponseDataVO(ResponseStatusCode.CUSTOMEXCEPTION);
}

1.2 基类 Action/Controller 异常处理

在应用广泛的 SSH 或是 SSM 框架项目中,一般存在着多个 xxxAction / xxxController 控制层,而它们在异常处理方面又存在着很多的共性,这样就不太适合在每个 xxxAction / xxxController 类中都嵌入一个对应的异常处理方法。因此我们可以将异常处理方法抽取到一个统一继承的基类中,然后所有的 xxxAction / xxxController 统一继承基类即可。

基类 BaseAction / BaseController:

代码语言:javascript
复制
public class BaseAction {    
@ExceptionHandler(Exception.class)    
public ResponseDataVO handleException(Exception e) {        
        return new ResponseDataVO(ResponseStatusCode.CUSTOMEXCEPTION);    
    }
}
// or
public class BaseController {    
    @ExceptionHandler(Exception.class)    
    public ResponseDataVO handleException(Exception e) {        
        return new ResponseDataVO(ResponseStatusCode.CUSTOMEXCEPTION);    
    }
}

UserController 通过继承 BaseAction / BaseController 完成异常处理:

代码语言:javascript
复制
@RestController@RequestMapping("/sys")
public class LoginController extends BaseAction {
    @PostMapping("/login")
    public ResponseDataVO login(@RequestBody UserLoginReqVO userLoginReqVO) {
        // 具体业务处理省略        
        ...        
        doSomething();    
    }
}
// or
@RestController
@RequestMapping("/sys")
public class LoginController extends BaseController {
    @PostMapping("/login")
    public ResponseDataVO login(@RequestBody UserLoginReqVO userLoginReqVO) {
        // 具体业务处理省略        
        ...        
        doSomething();    
    }
}

2. @ControllerAdvice 注解

对于使用基类 BaseAction / BaseController 完成统一异常处理也存在着缺点,那就是代码耦合度高,一旦开发人员编写 xxxAction / xxxController 时忘记继承 BaseAction / BaseController 基类,发生异常时又会直接抛到用户面前。如若想去除异常捕获的代码耦合度,我们可以使用 @ControllerAdvice 和 @ExceptionHandler 注解结合完成全局异常处理。

代码语言:javascript
复制
@ControllerAdvice
@ResponseBody
public class ExceptionHandlerAdvice {

    @ExceptionHandler(Exception.class)
    public ResponseDataVO handleException(Exception e) {
        return new ResponseDataVO(ResponseStatusCode.CUSTOMEXCEPTION);    
    }

}

在该类中,可以定义多个类别的异常捕获方法,不同的方法用于捕获不同类别的异常情况,例如专门捕获 SQL 异常的方法、专门捕获自定义异常的方法等等,也可以直接使用上面代码,在一个方法中处理所有的异常信息。

另外,在 ExceptionHandlerAdvice 类中的 @ExceptionHandler 注解是用来指明用户要捕获异常类型,这样发生异常时可以精确匹配到该方法,即如果这里指定为自定义异常类 CustomException,则其他异常就不会进到捕获自定义异常的方法中。

例如:

自定义异常类 BusinessException,代码如下:

代码语言:javascript
复制
public class BusinessException extends Exception {
    //业务类型
    private String bizType;
    //业务代码
    private int bizCode;
    //错误信息
    private String message;

    public BusinessException(String bizType, int bizCode, String message){
        super(message);
        this.bizType = bizType;
        this.bizCode = bizCode;
        this.message = message;
    }

    public BusinessException(String message){
        super(message);
        this.bizType = "";
        this.bizCode = -1;
        this.message = message;
    }

    public BusinessException(String bizType, String message){
        super(message);
        this.bizType = bizType;
        this.bizCode = -1;
        this.message = message;
    }

    public BusinessException(int bizCode, String message){
        super(message);
        this.bizType = "";
        this.bizCode = bizCode;
        this.message = message;
    }
    // 省略 getter/setter 方法
}

ExceptionHandlerAdvice 类中新增 businessException 方法捕获自定义异常,代码如下:

代码语言:javascript
复制
@ControllerAdvice
@ResponseBody
public class ExceptionHandlerAdvice {
    @ExceptionHandler(Exception.class)
    public ResponseDataVO handleException(Exception e) {
        return new ResponseDataVO(ResponseStatusCode.CUSTOMEXCEPTION);    
    }

    // 自定义异常捕获
    @ExceptionHandler(BusinessException.class)
    public ResponseDataVO businessException(BusinessException e) {
        return new ResponseDataVO(ResponseStatusCode.CUSTOMEXCEPTION);    
    }

}

小结

通过以上的学习,大家应该了解了 @ExceptionHandler 和 @ControllerAdvice 这两个注解的用法,对于全局异常处理有了一定的认识,为了方便对异常的统一管理,SpringMVC、Spring Boot 提供了 @ControllerAdvice 注解对异常进行统一的处理,拿到这些异常信息后,可以做一些处理,比如提供一个统一的 Web 界面查看异常信息,或者捕捉到异常信息后,以发送短信或是邮件形式通知到相关技术人员,可以帮助其开发人员快速发现并定位问题,减少以往通过查看线上日志文件排查问题繁琐过程的时间。而 @ControllerAdvice 注解的作用远远不止这些,还包括全局数据绑定和全局数据预处理等,有兴趣想了解更多相关信息的可以去 Spring 官方文档中查阅学习。

——> End <——

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码上修行 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1 单一 Action/Controller 异常处理
相关产品与服务
短信
腾讯云短信(Short Message Service,SMS)可为广大企业级用户提供稳定可靠,安全合规的短信触达服务。用户可快速接入,调用 API / SDK 或者通过控制台即可发送,支持发送验证码、通知类短信和营销短信。国内验证短信秒级触达,99%到达率;国际/港澳台短信覆盖全球200+国家/地区,全球多服务站点,稳定可靠。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档