SpringBoot基础教程2-1-3 异常处理规范

1. 概述

异常处理,在平时业务处理中不可避免;但是,阅读代码最头疼的就是看到一堆try-catch语句,业务逻辑参杂其中,极难维护;那要怎样优雅的处理异常呢?请耐心阅读全文。

2. 不负责任的处理异常

直接抛出异常或遗漏未捕获异常,会怎样?Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异常内容

@RestController

public class BadExceptionController {

@GetMapping("/bad")

public String bad(){

// todo 业务逻辑

​ Object object = null;

// 模拟空指针异常

object.toString();

​ return "success";

}

}

上述代码极不负责,看看测试结果

SpringBoot基础教程2-1-3 异常处理规范

当调用者看到这个结果,估计一脸懵

3. 丑陋的异常处理

常见的异常处理,在try-catch块中,手动封装返回对应结果;该方法相比上面,虽然封装了异常,但是异常处理逻辑,嵌在业务逻辑中,当要修改业务逻辑时,也不可避免的新增对于异常处理逻辑,耦合度非常高

@RestController

public class UglyExceptionController {

​ @GetMapping("/ugly")

public Map ugly(){

Map result = new HashMap<>();

// TODO 直接捕获所有代码块,然后在 cache

try {

int i = 10 / 0;

result.put("code", "200");

result.put("data", "具体返回的结果集");

} catch (Exception e) {

result.put("code", "500");

result.put("message", "请求错误");

}

return result;

}

}

4. 优雅的异常处理

创建自定义业务异常类

public class BusinessException extends RuntimeException{

​ public BusinessException(String message) {

super(message);

}

}

创建通用响应处理类

@Data

public class R implements Serializable {

​ private T data; //服务端数据

private int status = 0; //状态码,0:成功,1:失败

private String msg = ""; //描述信息

public static R isOk() {

return new R().msg("成功");

}

​ public static R isFail() {

return new R().status(1).msg("失败");

}

​ public static R isFail(Throwable e) {

return isFail().msg(e);

}

​ public R msg(Throwable e) {

this.setMsg(e.toString());

return this;

}

public R data(T data) {

this.setData(data);

return this;

}

​ public R msg(String msg){

this.setMsg(msg);

return this;

}

​ public R status(int status) {

this.setStatus(status);

return this;

}

}

这里推荐一款神级插件lombok,pom.xml添加如下依赖,主要作用是使用注解在编译时生成基础方法

org.projectlombok

lombok

1.16.20

provided

创建统一异常处理类(重点)

// 如果要验证BadException 和 UglyException请注释@ControllerAdvice

@RestControllerAdvice

public class GlobalExceptionHandler {

​ @ExceptionHandler(value = BusinessException.class)

public R businessExceptionHandler(BusinessException exception) {

return R.isFail(exception);

}

​ @ExceptionHandler(value = Exception.class)

public R exceptionHandler(Exception exception) {

return R.isFail(exception);

}

}

  • @ControllerAdvice 捕获 Controller 层抛出的异常,如果添加@ResponseBody 返回信息则为JSON 格式。
  • @RestControllerAdvice 相当于 @ControllerAdvice 与 @ResponseBody 的结合体。
  • @ExceptionHandler 统一处理一种类的异常,减少代码重复率,降低复杂度。

创建Controller

@RestController

public class BusinessController {

@GetMapping("/business/{param}")

public R business(@PathVariable String param){

​ if("ok".equals(param)){

return R.isOk();

} else {

throw new BusinessException("business exception: param = " + param);

}

}

}

测试结果如下

SpringBoot基础教程2-1-3 异常处理规范

SpringBoot基础教程2-1-3 异常处理规范

5. 工程目录

SpringBoot基础教程2-1-3 异常处理规范

6. 结束语

本文源码:GitHub,Mkeeper666;码云,Mkeeper


分享到:


相關文章: