springboot2.x使用@RestControllerAdvice实现通用异常捕获

文章目录

    • demo地址
    • 实现效果
    • 引入
    • 基础类准备
      • 1.通用枚举与错误状态枚举
      • 2.定义通用返回结果
      • 3.自定义业务异常
    • 统一异常捕获
    • 测试

demo地址

demo工程地址

实现效果

  • 当我们输入1时,正常的返回通用的响应结果
  • 当我们输入2时,抛出异常,被捕获然后返回通用的结果
  • 可以看到两者的数据结构都是完全一样的

java通用异常捕获效果展示

引入

很多时候,当一个javaweb项目在运行的过程中出现一些不可预值的错误时会抛出异常,例如下方我们在接口直接抛出一个运行时异常:

请添加图片描述
对应接口的响应就变成如下图所示:

请添加图片描述
这时的返回结果往往和我们与前端约定好的响应结果的数据结构出入很大,而且也不方便我们去排查错误,并且对用户体验也不好,这时就需要我们配置一个统一的异常捕获,对各种异常进行统一数据结构的返回,方便前端展示对应的错误,我们也可以在捕获到异常后进行对应的日志记录,方便后续排查。

基础类准备

1.通用枚举与错误状态枚举

我们首先需要和前端沟通好统一的返回结果的数据结构和一些常见的错误状态,这里我们使用一个错误状态枚举来展示业务内的一些报错,为了枚举更好的拓展性,这里我们先封装一个基础枚举类,如下:

  • 封装通用枚举的好处,可以参考我的这几个视频讲解:
  • 封装通用枚举1
  • 封装通用枚举2(封装选项生成)
  • 封装通用枚举3(按类型获取枚举选项接口)
/*** @Author: lzp* @description: 通用枚举* @Date: 2022/9/24*/
public interface BaseEnum<P> {/*** 获取标题*/String getTitle();/*** 获取值*/P getValue();/*** 通过value获取枚举对象* 2022-12-09日使用泛型优化此方法** @param enumClass 枚举的类对象* @param value     值* @return*/static <T extends BaseEnum> T valueOf(Class<T> enumClass, Object value) {if (value == null) {return null;}T[] enumConstants = enumClass.getEnumConstants();if (enumConstants == null) {return null;}for (T enumConstant : enumConstants) {if (value.equals(enumConstant.getValue())) {return enumConstant;}}return null;}}

接着,我们实现通用枚举接口,定义通用状态码枚举如下:

  • 这样可以把我们系统中可预知的异常全部定义在错误码枚举中
  • 我们可以给对应业务模块的错误码命名为指定范围内,例如用户相关的错误咱们控制在 10001 ~ 10100之间
import lombok.Getter;
import online.longzipeng.mywebdemo.enums.BaseEnum;/*** @Author: lzp* @Date:2023/10/30* @description: 通用错误状态码*/
@Getter
public enum ErrorCodeEnum implements BaseEnum<Integer> {// 通用错误状态码SUCCESS(0, "成功"),ERROR(-1, "失败"),// 用户相关异常  10001 ~ 10100USER_LOGIN_ERROR(1001,"账号或密码错误!"),;public final Integer value;public final String title;ErrorCodeEnum(Integer value, String title) {this.value = value;this.title = title;}}

2.定义通用返回结果

我们与前端约定好通用的返回结果的数据结构,例如都带有code,msg,data,分别表示该接口的响应状态码,错误消息,返回数据:

  • 为了通用防止任何数据类型,这里我们使用泛型来指定响应的data
  • 为了方便通用的返回,例如一般修改接口不需要返回数据,此时在咱们就可以指定调用静态方法 Result.success();
package online.longzipeng.mywebdemo.commen;import lombok.Data;
import online.longzipeng.mywebdemo.commen.exception.ErrorCodeEnum;import java.io.Serializable;/*** 通用响应** @author lzp*/
@Data
public class Result<T> implements Serializable {private static final long serialVersionUID = 1L;/*** 编码:0表示成功,其他值表示失败*/private int code = ErrorCodeEnum.SUCCESS.value;/*** 消息内容*/private String msg = ErrorCodeEnum.SUCCESS.title;/*** 响应数据*/private T data;public static <T> Result<T> error() {return generate(ErrorCodeEnum.ERROR.value, ErrorCodeEnum.ERROR.getTitle());}/*** 快速生成返回结果* @param code 状态码* @param msg 对应消息内容*/public static <T> Result<T> generate(int code, String msg) {Result<T> result = new Result();result.setCode(code);result.setMsg(msg);return result;}public static <T> Result<T> success() {return new Result<>();}public static <T> Result<T> success(T data) {Result<T> result = new Result<>();result.setData(data);return result;}}

3.自定义业务异常

因为运行时异常是一种特殊的异常,不需要我们显示的抛出和try catch处理,所以很适合用于做我们的自定义业务异常,然后我们希望业务出错了也统一返回Result的数据结构,所以咱们自定义的异常也需要包含 code和msg字段

package online.longzipeng.mywebdemo.commen.exception;import lombok.Data;/*** 通用异常处理*/
@Data
public class ServiceException extends RuntimeException {private static final long serialVersionUID = 1L;/*** 错误码*/private int code;/*** 错误信息*/private String msg;public ServiceException(int code) {this.code = code;}public ServiceException(int code, String msg) {this.code = code;}public ServiceException(String msg) {super(msg);this.code = ErrorCodeEnum.ERROR.value;this.msg = msg;}/*** 使用通用错误枚举快速创建异常*/public ServiceException(ErrorCodeEnum errorCodeEnum) {this.code = errorCodeEnum.getValue();this.msg =errorCodeEnum.getTitle();}
}

统一异常捕获

在springboot2.x中,咱们可以通过@ControllerAdvice注解与@ExceptionHandler注解来实现统一的异常捕获与处理,为了方便返回结果,这里我们使用@RestControllerAdvice注解返回JSON格式的响应,用于快速构建RESTful风格的程序。

如下:

  • 这里我们直接捕获到了自定义的业务异常,从中取出结果并返回Result对象
  • 捕获Exception异常,当发生不可预知的异常时,在此统一捕获,并打印错误日志
package online.longzipeng.mywebdemo.commen.exception;import online.longzipeng.mywebdemo.commen.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** 通用异常处理器*/
@RestControllerAdvice
public class ServiceExceptionHandler {private Logger logger = LoggerFactory.getLogger(getClass());/*** 处理自定义异常*/@ExceptionHandler(ServiceException.class)public Result handleRenException(ServiceException e) {return Result.generate(e.getCode(),e.getMsg());}/*** 处理未知异常*/@ExceptionHandler(Exception.class)public Result handleException(Exception e) {logger.error(e.getMessage(), e);return Result.error();}
}

测试

我们创建一个用于测试的controller,并在其中手动抛出一个业务异常,如下:

package online.longzipeng.mywebdemo.controller;import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import online.longzipeng.mywebdemo.commen.Result;
import online.longzipeng.mywebdemo.commen.exception.ErrorCodeEnum;
import online.longzipeng.mywebdemo.commen.exception.ServiceException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;/*** @Author: lzp* @description:* @Date: 2023/10/30*/
@RestController
@RequestMapping("/test")
@Api(tags = "测试接口")
public class TestController {@GetMapping("/error")@ApiOperation("测试异常抛出")public Result<String> testError(@RequestParam @ApiParam("1 正常 2抛出错误") Integer type) {if (type == 2) {throw new ServiceException(ErrorCodeEnum.USER_LOGIN_ERROR);}return Result.success("你好呀~");}}

显示结果如下:

  • 当我们输入1时,正常的返回通用的响应结果
  • 当我们输入2时,返回对应的错误
  • 可以看到两者的数据结构都是完全一样的

java通用异常捕获效果展示

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/126983.shtml

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

相关文章

react-组件生命周期

一、生命周期阶段 官方文档&#xff1a;https://zh-hans.legacy.reactjs.org/docs/react-component.html React组件生命周期可分为三个阶段&#xff1a;挂载、更新、卸载 挂载&#xff1a;当组件实例被创建并插入 DOM 中时。其生命周期调用顺序如下&#xff1a; constructor()s…

【c++Leetcode】287. Find the Duplicate Number

问题入口 思想&#xff1a;Floyds Tortoise and Hare 这个算法除了可以检测是否有环&#xff08;问题入口&#xff09;&#xff0c;还可以用来检测重复数。当然这还需要一个慢指针才能实现。具体请点击标题跳转到原视频&#xff0c;这里是把内容再梳理一遍。如果有不对的地方…

Web自动化测试之图文验证码的解决方案

对于web应用程序来讲&#xff0c;处于安全性考虑&#xff0c;在登录的时候&#xff0c;都会设置验证码&#xff0c; 验证码的类型种类繁多&#xff0c;有图片中辨别数字字母的&#xff0c;有点击图片中指定的文字的&#xff0c;也有算术计算结果的&#xff0c;再复杂一点就是滑…

无测试组织:测试团队的敏捷转型

文章目录 写在前面01 从测试角度理解敏捷理念什么是敏捷&#xff1f;测试人员应该怎样理解敏捷理念&#xff1f;敏捷宣言对于测试活动的启发与思考总结如下敏捷原则12条敏捷实践框架为什么要做敏捷 02 什么是敏捷测试03 敏捷测试为什么会失败04 诊断脑暴会的成果示例测试团队转…

表格识别软件:科技革新引领行业先锋,颠覆性发展前景广阔

表格识别软件的兴起背景可以追溯到数字化和自动化处理的需求不断增加的时期。传统上&#xff0c;手动处理纸质表格是一项费时费力的工作&#xff0c;容易出现错误&#xff0c;效率低下。因此&#xff0c;开发出能够自动识别和提取表格数据的软件工具变得非常重要。 随着计算机…

使用 Python 进行自然语言处理第 5 部分:文本分类

一、说明 关于文本分类&#xff0c;文章已经很多&#xff0c;本文这里有实操代码&#xff0c;明确而清晰地表述这种过程&#xff0c;是实战工程师所可以参照和依赖的案例版本。 本文是 2023 年 1 月的 WomenWhoCode 数据科学跟踪活动提供的会议系列文章中的一篇。 之前的文章在…

【深度学习基础】专业术语汇总(欠拟合和过拟合、泛化能力与迁移学习、调参和超参数、训练集、测试集和验证集)

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

linux的环境安装以及部署前后端分离后台接口

⭐⭐ linux专栏&#xff1a;linux专栏 ⭐⭐ 个人主页&#xff1a;个人主页 目录 一.linux安装环境 1.1 jdk和tomcat的安装配置 1.1.1 解压jdk和tomcat的安装包 解压jdk安装包 解压tomcat安装包 1.2 jdk环境变量配置 1.3 tomcat启动 1.4 MySQL的安装 二.部署前后端分离…

机器学习快速入门教程 Scikit-Learn实现

机器学习是什么? 机器学习是一帮计算机科学家想让计算机像人一样思考所研发出来的计算机理论。他们曾经说过,人和计算机其实本没有差别,同样都是一大批互相连接的信息传递和存储元素所组成的系统。所以有了这样的想法,加上他们得天独厚的数学功底,机器学习的前身也就孕育而生…

RHCSA -- VMware虚拟机配置及破解密码

一、配置虚拟机 1、开启VMware&#xff08;自定义&#xff09; 2、设置虚拟机硬件兼容性&#xff08;默认&#xff09; 3、稍后安装虚拟机操作系统 4、选择为Linux的虚拟机 5、虚拟机机名 6、设置虚拟机处理器 7、设置虚拟机所连接的网络类型 8、选择磁盘类型 9、设置所选磁…

【源码】医院绩效考核系统-对接HIS核算

医院绩效考核系统&#xff0c;它需要和his系统进行对接&#xff0c;按照设定周期&#xff0c;从his系统获取医院科室和医生、护士、其他人员工作量&#xff0c;对没有录入信息化系统的工作量&#xff0c;绩效考核系统设有手工录入功能&#xff08;可以批量导入&#xff09;&…

CSS标点符号换行问题

最近遇到一个奇怪的现象,元素中中文文本正常显示,但是加了一堆符号后中文文本居然换行了. div{width: 200px;border: 1px solid blue;word-break: break-all;} <div>文本</div>经过研究发现&#xff0c;因为标点符号不允许出现在行首和行尾&#xff0c;连带着符号…

Kafka - 监控工具 Kafka Eagle:实时洞察Kafka集群的利器

文章目录 引言Kafka Eagle简介Kafka Eagle的特点Kafka Eagle的优势使用Kafka Eagle的步骤结论 引言 在现代大数据架构中&#xff0c;Apache Kafka已成为一个不可或缺的组件&#xff0c;用于可靠地处理和传输大规模的数据流。然而&#xff0c;随着Kafka集群规模的不断增长&…

QT基础学习笔记

文章目录 1 概述1.1 优点1.2 QT成功使用案例1.3 安装教程1.3.1 在线安装流程1.3.2 离线安装流程 2 创建工程2.1 快捷键2.1.1 常用快捷键2.1.2 修改快捷键 2.2 proj文件 3 对象树4 信号和槽4.1 自定义信号和槽4.1.1 信号连接信号4.1.2 一个信号连接多个槽函数4.1.3 多个信号连接…

算法---缺失的第一个正数

题目 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。示例 1&#xff1a;输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 示例 2&#xff1a;输入&#xff1a;nums …

C++数据结构算法篇Ⅰ

C数据结构算法篇Ⅰ &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C算法 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 主要内容讲解数据结构中的链表结构 文章目录 C数据…

WSL安装Ubuntu

先安装wsl2 安装Ubuntu 打开windows商店&#xff0c;搜索对应版本的Ubuntu&#xff0c;点击获取进度跑完后&#xff0c;点击打开&#xff0c;就可以完成安装 删除Ubuntu版本 wsl --unregister Ubuntu-18.04安装位置迁移 正常情况下Ubuntu是被安装在C盘&#xff0c;我们需要…

什么是数字展览馆,数字展览馆有什么应用前景

引言&#xff1a; 数字展览馆作为一种新兴的文化艺术展示形式&#xff0c;以数字化技术和虚拟现实为基础&#xff0c;正在逐渐改变传统展览的方式。 一、什么是数字展览馆&#xff1f; 1.定义 数字展览馆是利用数字技术和虚拟现实技术打造的一种线上文化艺术展示平台。通过虚…

@reduxjs/toolkit配置react-redux解决createStore或将在未来被淘汰警告

通常 我们用redux都需要通过 createStore 但目前 你去用它 基本都会被划线 甚至有点厉害的的编辑器 他会直接告诉你这个东西基本快被弃用了 这个应该大家都知道 最好不要用已经被明确未来或弃用的语法 因为一旦弃用这个系统就需要维护 而且说 一般会被淘汰的语法 本身也就是有…

2023年免费CRM软件盘点:14款热门工具全面比较(含开源)

在初创企业或小型企业阶段&#xff0c;特别是在预算有限且客户管理需求较为基础的情境下&#xff0c;使用免费的CRM系统通常是一个理智的选择。这类系统虽然在功能上可能不如付费版本丰富&#xff0c;但基本的客户信息管理、销售跟踪和沟通记录等核心功能通常都能满足需求。 对…