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

news2024/9/21 23:18:39

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

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.coloradmin.cn/o/2153573.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

20240921在友善之臂的NanoPC-T6开发板上确认宸芯的数传模块CX6602N的AT命令

console:/dev # cat ttyUSB1 & console:/dev # echo AT > ttyUSB1 20240921在友善之臂的NanoPC-T6开发板上确认宸芯的数传模块CX6602N的AT命令 2024/9/21 21:03 【必须】Android12/Linux(Buildroot)都必须要! 4、【Android12默认打开U…

电脑硬件-机械硬盘

简介 机械硬盘是电脑的主要存储媒介之一,通常用于存储一些文件资料或者学习视频笔记等比较大的内容。 结构 采用磁盘存储数据,使用温彻斯特的结构,特有四个特点: 1.磁头、盘片和运动机构安装在一个密封的腔体内。 2.盘片告诉旋…

一图快速看懂flink source的设计实现

文章目录 整体来说多个处理流程是解偶的,这样可以在面对多数据源情况下,能更加的灵活。 下面只展示了,主要的一些流程 下面补充一点,读取文件状态的保存,切分信息用了一个 ListState 来保存。具体要保存的信息&#x…

day2-1 app端文章查看

首先一共三张表 然后大致过程就是三层架构 用mp实现 具体出现的问题 1 测试的时候后端代码启动不了 先在maven clean一下 具体流程 然后执行完之后建议把这三个模块的target文件删除一下再运行 最后的话 如果还是报错 也是正常的 因为后边的东西都没写有些文件没有用到 2…

常见的中间件漏洞

Tomcat CVE-2017-12615 访问主页进行抓包 修改传参方式为put 放包进行连接 后台弱⼝令部署war包 访问主页试用默认账号密码tomcat/tomcat进行登录后 将哥斯拉生成的jsp木马文件压缩城成zip文件,然后再修改zip后缀文war 然后进行上传 使用哥斯拉进行测试连接 CVE-…

基于SpringBoot+Vue的在线酒店预订系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…

微服务——网关登录校验(一)

1.网关登录校验 微服务中的网关登录校验是微服务架构中常见的一种安全机制,用于在请求到达微服务之前,对用户的身份进行验证,确保只有合法的用户才能访问相应的服务。 在微服务架构中,每个微服务都是独立部署的,它们之…

Apipost IDEA插件新升级,Apipost Helper上架IDEA插件市场

大家好!今天向大家介绍一个非常方便的IDEA插件——Apipost Helper!相信很多使用过Apipost的朋友在开发过程中都希望能够直接将编写好的API同步至Apipost,而无需手动填写。前段时间,Apipost推出了Apipost IDEA插件的内测版&#xf…

macOS平台编译libidn2库给iOS及macOS用

1.克隆源码: git clone https://gitlab.com/libidn/libidn2.git --recursive 2.安装依赖库: pkg-config也要安装 3.启动bootstrap生成configure 配置成功 configure生成成功

概率论与数理统计(2)

第一节博客已经整理了求导的公式,一些常用的概念。链接如下:高等数学基础(1)-CSDN博客。 第二节博客整理了微积分的公式及其相关概念。链接如下:高等数学基础(2)——微积分-CSDN博客 第三节博客…

主流卷积神经网络CNN总结

ResNet(2015)残差神经网络 残差结构 ResNet50具体卷积结构图 ResNeXt(2016)加入了分组卷积的思想,将原ResNet网络中的block替换成由group分组的block,两者得到的feature map一致,只是参数量更少…

计算机网络(月考一知识点)

文章目录 计算机网络背诵默写版计算机网络知识点(月考1版) 计算机网络背诵默写版 为我自己留个印记,本来荧光笔画的是没记住的,但是后面用紫色的,结果扫描的时候就看不见了。 计算机网络知识点(月考1版&a…

耳夹式耳机值得买吗?揭秘耳夹式耳机六大避坑指南!

耳夹式耳机值得买吗?这是很多人的疑问,但是夹耳式耳机火起来跟当下人们对健康运动的需求密不可分,入耳式耳机照顾了听音需求就很难兼顾环境音,还有耳部健康和佩戴舒适度等等,而运动时半入耳式耳机又容易掉,…

T4—猴痘识别

🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 1.导入数据 #设置gpu from tensorflow import keras from tensorflow.keras import layers,models import os, PIL, pathlib import matplotlib.pyplot as pl…

【刷题—双指针】复写0、三数之和、四数之和

目录 一、复写0二、三数之和三、四数之和 一、复写0 题目: 注意:题目要求是原数组上复写 思路: 一、确定最后一个复写的位置。定义两个变量cur等于0,dest等于-1,让cur去遍历数组。如果cur指向的元素是0,…

[SAP ABAP] 创建数据元素

我们可以使用事务码SE11创建数据元素 输入要创建的数据类型的名称,然后点击创建 选择数据元素并进行确定 输入简短描述并为数据元素分配一个域,会自动带出数据类型以及长度 创建域可参考该篇文章 创建域https://blog.csdn.net/Hudas/article/details/…

Hive企业级调优[6]——HQL语法优化之任务并行度

目录 HQL语法优化之任务并行度 优化说明 Map端并行度 Reduce端并行度 优化案例 HQL语法优化之任务并行度 优化说明 对于分布式计算任务来说,设置一个合理的并行度至关重要。Hive的计算任务依赖于MapReduce框架来完成,因此并行度的调整需要从Map端和…

YOLOv10 简介

YOLOv10,由清华大学的研究人员基于 Ultralytics Python 包构建,引入了一种全新的实时目标检测方法,该方法解决了以往 YOLO 版本中后处理和模型架构方面的不足。通过消除非极大值抑制(NMS)并优化各种模型组件&#xff0…

C# 技巧在 foreach 循环中巧妙获取索引

目录 前言 使用 LINQ 和扩展方法 直接在 LINQ 查询中使用 使用 LINQ 的 Select() 与 Enumerable.Range() 总结 最后 前言 在C#中foreach 循环是处理集合的常见方式,因其简洁性和易读性而广受青睐。 但是在某些情况下,我们需要同时获取集合中元素的…

mysql中的json查询

首先来构造数据 查询department里面name等于研发部的数据 查询语句跟普通的sql语句差不多,也就是字段名要用到path表达式 select * from user u where u.department->$.name 研发部 模糊查询 select * from user u where u.department->$.name like %研发%…