使用spring boot实现异常的统一返回

在这个前后端分离的时代,一个 统一的数据格式非常重要。本次我们实现用spring boot实现一下返回给前端数据的统一格式,不再出现服务器500的错误。

新建一个spring boot项目,并导入knife4j的依赖。

写一个controller控制器,用来是实现测试http的请求

复制代码
@RestController
public class TestController {

@GetMapping("/test")
public  String test(){
int i=1/0;
    return "一个test测试请求";
}
}

发送请求测试:

异常的统一主要依赖于两个注解:
@ControllerAdvice:

Controller增强器,给controller层增加统一的操作和处理

@ExceptionHander

捕获controller抛出的异常,并进行处理;

自定义异常处理:

1、自定义一个类Result,用来实现返回给前端的统一格式:

复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> implements Serializable {
    private static final long serialVersionUID = 1L;
private Integer code;
private String message;
private T data;
}

2、创建一个类ResultException,继承RuntimeException异常

复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ResultException extends RuntimeException{
    private Integer code;
    private String message;
}

3、创建一个VoResultException 类,用来实现具体的逻辑:

复制代码
@RestControllerAdvice
public class VoResultException {

//    自定义异常处理类
@ExceptionHandler(ResultException.class)
public Result errorResult(ResultException resultException){
return new Result(resultException.getCode(),resultException.getMessage(),null);
}

}

@RestControllerAdvice注解是@ControllerAdvice和@ResponseBody注解的结合,标识返回的数据是json类型

至此,我们就实现了全部的工作。现在,在你想要抛出异常的地方直接使用即可(直接抛出ResultException异常)

复制代码
@GetMapping("/test")
public  String test(){
    throw new ResultException(10001,"测试异常");
    
}

发送请求测试:

可以返回了统一的数据,但是这个异常是我们自定义的。所以不能处理程序中的错误

如下图这个错误:

复制代码
@GetMapping("/test")
public  String test(){
    int i=1/0;
    throw new ResultException(10001,"测试异常");

}

测试请求:

由于这个异常是在程序运行中出现的,属于RunException异常,我们自定义的异常不能够捕获到。 这时,我们可以在自定义的异常处理器VoResultException类中再加入全局异常处理器。

如下所示:

复制代码
@RestControllerAdvice
public class VoResultException {
//    自定义异常处理类
@ExceptionHandler(ResultException.class)
public Result errorResult(ResultException resultException){
return new Result(resultException.getCode(),resultException.getMessage(),null);
}

//全局异常处理类
    @ExceptionHandler(Exception.class)
    public Result error(Exception e){
    return new Result(1001,e.getMessage(),null);
    }
    
}

加入了全局异常处理时,抛出的RunException异常就可以自动捕获了。

小插曲:

@ExceptionHandler(ResultException.class)注解里面是要捕获的异常的类型,下面的方法参数中也一定要传入与这个类型一样的类队象 或者 满足继承关系(这一点是非常重要的,不然它不能自动捕获异常)

因为有人还是搞不懂,这个关系,私下里问我。我再一次修改了,这一次更加详细:

在使用 @ExceptionHandler 注解时,注解中的类对象 并不一定要与方法参数的对象类型完全一样,但是要满足以下条件:

  1. 类对象必须是方法参数对象的父类或接口。这意味着注解中的类对象可以是方法参数对象的超类、接口或实现类。

  2. 类对象不能是方法参数对象的子类。如果注解中的类对象是方法参数对象的子类,那么该注解将不会匹配到该方法,而是匹配到更具体的子类处理方法(如果有定义)。

我们再发一次请求:

可以看到by zero这个异常被自动捕获了。

我们在正常的后端开发中也是这样搞得:

一般我们定义两个@ExceptionHandler。

一个是自定义异常,用来在项目中抛出我们自定义的异常(由于这个自定义的异常是继承RunException得来的,所以不能处理项目在运行时的异常,只能手动抛出,也就是我们已经预先知道的异常)

一个是全局异常,用来捕获我们在项目中遇到的其他异常。可以这样说,除了我们手动抛出的自定义异常,其他的都需要全局异常来捕获并抛出。但是全局异常的表达并不能像我们自定义的异常一样清晰,这个是虚拟机自动抛出的。

相关推荐
小码哥_常3 小时前
别再被误导!try...catch性能大揭秘
后端
无巧不成书02184 小时前
30分钟入门Java:从历史到Hello World的小白指南
java·开发语言
苍何5 小时前
30分钟用 Agent 搓出一家跨境网店,疯了
后端
ssshooter5 小时前
Tauri 2 iOS 开发避坑指南:文件保存、Dialog 和 Documents 目录的那些坑
前端·后端·ios
追逐时光者5 小时前
一个基于 .NET Core + Vue3 构建的开源全栈平台 Admin 系统
后端·.net
程序员飞哥5 小时前
90后大龄程序员失业4个月终于上岸了
后端·面试·程序员
zs宝来了6 小时前
Playwright 自动发布 CSDN 的完整实践
java
彭于晏Yan7 小时前
Redisson分布式锁
spring boot·redis·分布式
吴声子夜歌7 小时前
TypeScript——基础类型(三)
java·linux·typescript
GetcharZp7 小时前
Git 命令行太痛苦?这款 75k Star 的神级工具,让你告别“合并冲突”恐惧症!
后端