当前位置: 首页 > article >正文

Spring:项目中的统一异常处理和自定义异常

介绍异常的处理方式。在项目中,都会进行自定义异常,并且都是需要配合统一结果返回进行使用。

1.背景引入

(1)背景介绍

为什么要处理异常?如果不处理项目中的异常信息,前端访问我们后端就是显示访问失败的,所以我们需要处理。但是单单处理还不够,还需要将信息返回给前端;因为异常是一类问题,所以我们可以统一进行处理,也就是统一异常处理。

(2)没有处理异常时

看一段代码:

@Slf4j
@RequestMapping("/test")
@RestController
public class TestController {


    @RequestMapping("/hello")
    public String hello() {
        log.info("我被前端调用了,嘤嘤嘤~");
        int a = 10/0;
        return "hello";
    }

}

通过url进行访问:

后端日志:

所以这就是没有进行异常处理的后果

(3)简单处理异常后

下面这段代码就会对异常进行捕获,并且返回异常的具体信息

@Slf4j
@ResponseBody
@ControllerAdvice
public class ExceptionAdvice {


    @ExceptionHandler(Exception.class)
    public String exception(Exception e) {
        log.warn(e.getMessage());
        return e.getMessage();
    }
}

前端:

这样前端就知道了明确的异常信息,但是实际异常不会单独使用,都是作为一个Message封装到统一结果中进行返回。

2.异常使用方法

我们先在代码中定义一个简单的统一结果返回,用于介绍和学习异常

import lombok.Data;

@Data
public class Result {
    private String message;
    private int code;

    public Result(String message,int code) {
        this.message = message;
        this.code = code;
    }

    public static Result fail(String message) {
        return new Result(message,1314);
    }

}

(1)统一异常模版

controller:

import lombok.extern.slf4j.Slf4j;
import org.ljy.testdemo.common.Result;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RequestMapping("/test")
@RestController
public class TestController {

    @RequestMapping("/hello")
    public String hello() {
        int a = 10/0;
        return "hello";
    }

    @RequestMapping("/heihei")
    public Result heihei() {
        return Result.fail("只因你实在是太美~");
    }

}

异常捕获: 

import lombok.extern.slf4j.Slf4j;
import org.ljy.testdemo.common.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@Slf4j
@ResponseBody
@RestControllerAdvice
public class ExceptionAdvice {

    @ExceptionHandler
    public Result exception(Exception e) {
        log.error(e.getMessage(), e);
        return Result.fail(e.getMessage());
    }
}

我们通过前端就行访问:

即时后端发生了异常,前端也能收到格式化的数据,大大提高了可读性。

(2)注解解析

写法一:类@RestControllerAdvice + 方法@ExceptionHandler

表示该类下的所有方法返回的都是数据

写法二:类@ControllerAdvice + 方法@ResponseBody + 方法@ExceptionHandler

表示该方法返回数据

写法三:类@ControllerAdvice + 类@ResponseBody + 方法@ExceptionHandler

表示该类下的所有方法返回的都是数据

其他写法:可以指定捕获异常的类型,也就是在@ExceptionHandler后面加上括号,指定异常的对象

@Slf4j
@RestControllerAdvice
public class ExceptionAdvice {

    @ExceptionHandler(Exception.class)
    public Result exception(Exception e) {
        log.error(e.getMessage(), e);
        return Result.fail(e.getMessage());
    }
}

为什么要加上@ResponseBody注解,不加的时候默认返回视图,就会产生异常,也就是下面的效果

3.使用自定义异常

这里的自定义异常也就是定义一个异常类,然后作为@ExceptionHandler捕获的对象

(1)先自定义一个普通的异常

步骤:实现Exception类或者其子类,然后写构造方法(记得先初始化父类),可以看情况重写几个方法

于是我们得到下面的自定义异常类

public class ApplicationException extends RuntimeException{

    //自定义的错误结果(里面包含错误码和错误信息)
    protected Result errorResult;


    //用于throw new ApplicationException(Result.fail("我走的是构造方法"))这种情况
    public Result getErrorResult() {
        return errorResult;
    }

    /**
     * 构造方法  用于填充信息
     */

    public ApplicationException(Result errorResult) {
        super(errorResult.getMessage());
        this.errorResult = errorResult;
    }

    public ApplicationException(String message) {
        super(message);
    }

    public ApplicationException(Throwable cause) {
        super(cause);
    }

    public ApplicationException(String message, Throwable cause) {
        super(message, cause);
    }
}

(2)再定义全局异常处理器

这里的全局异常处理器就是上面的统一异常处理,只需要多捕获一个自定义异常就可以了。

import lombok.extern.slf4j.Slf4j;
import org.ljy.testdemo.common.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@Slf4j
@ResponseBody
@ControllerAdvice
public class ExceptionAdvice {


    @ExceptionHandler(ApplicationException.class)
    public Result applicationExceptionHandler (ApplicationException e) {
        e.printStackTrace();
        // 打印日志
        if (e.getErrorResult() != null) {
            return e.getErrorResult();
        }
        // 一般不会为null,构造方法已经限制住了,但是保险一些
        if (e.getMessage() == null || e.getMessage().equals("")) {
            return Result.fail(e.getMessage());
        }
        // 返回具体的异常信息
        return Result.fail(e.getMessage());
    }

    //兜底捕获异常
    @ExceptionHandler(Exception.class)
    public Result exception(Exception e) {
        log.error(e.getMessage(), e);
        return Result.fail(e.getMessage());
    }
}

大致情况就这么写,接下来解析一下统一异常中的几种校验情况


http://www.kler.cn/news/314699.html

相关文章:

  • 通过Java设计模式提高业务流程灵活性的策略
  • 笔记:DrawingContext和GDI+对比简介
  • 【Python】探索 TensorFlow:构建强大的机器学习模型
  • PostgreSQL技术内幕11:PostgreSQL事务原理解析-MVCC
  • 区块链DAPP质押系统开发
  • python中迭代器和可迭代对象
  • 【系统架构设计师】特定领域软件架构(经典习题)
  • 边缘智能-大模型架构初探
  • WebGL基础知识快速入门
  • 安装nuxt3
  • 「iOS」viewController的生命周期
  • Android TV RecyclerView列表获得焦点左右换行
  • 如何在Mac上安装多个Python环境
  • Spring Mybatis PageHelper分页插件 总结
  • MySQL篇(SQL优化)(持续更新迭代)
  • Android Studio 开发快速获取开发版和发布版SHA1和MD5
  • 汽车美容服务管理系统的数据库设计与数据操作
  • nvm 下载node报错:Could not retrieve https://nodejs.org/dist/index.json.
  • 奇安信渗透2面经验分享
  • HarmonyOS第一课-应用程序框架基础习题答案
  • 邮件安全治理
  • 解决nginx代理SSE接口的响应没有流式返回
  • 详细分析Spring的动态代理机制
  • zynq的PS端mac与RTL8211F的连接要点
  • 微服务架构中的负载均衡与服务注册中心(Nacos)
  • Cursor免费 GPT-4 IDE 工具的保姆级使用教程
  • Spring01
  • C# 中的NPOI 库
  • 生物信息常用编辑器:轻量高效的VS Code
  • 山东潍坊戴尔存储服务器维修 md3800f raid恢复