异常封装类统一后端响应的数据格式

异常封装类 如何统一后端响应的数据格式

1. 背景

后端作为数据的处理和响应,如何才能和前端配合好,能够高效的完成任务,其中一个比较重要的点就是后端返回的数据格式。

没有统一的响应格式:

// 第一种:
{
    "data": -1
}

// 第二种:
{
  "timestamp": "2021-07-08T08:05:15.423+00:00",
  "status": 500,
  "error": "Internal Server Error",
  "path": "/wrong"
}

// 第三种:
hello,javadaily

如果你作为一个后端开发的人员将这样式的数据返回给前端的话,那你肯定会被骂屎,如果前后端都是你干那当我没说,所以一个格式规范的响应是至关重要的

有统一的响应格式:

// 规范的返回响应的格式
{
  "message":"ok",
  "code": 0,
  "data":{
      "id": 007,
      "userName": "xdm"
  }
}

认识到了响应格式的规范性那么我们就来讲解一个如何实现

2. 代码实现

  1. 实现逻辑

    • 编写一个异常信息枚举类(自定义错误码),将所有可能出现的异常信息通过枚举的方式列出来,方便后续使用
    • 编写一个通用的异常返回类(构建一个语法糖)参数可以是自定义的也可以是枚举类传入的
    • 编写一个异常返回的工具类,包含成功的返回和失败的返回
    • 编写一个基础的异常类来继承运行时异常(目的就是为了能被全局异常处理器捕获到)
    • 编写一个全局异常处理器通过ExceptionHandler来识别到不同的异常(自定的异常还是运行时异常)
  2. 具体实现

    1. 自定义错误码

      public enum ErrorCode {
      
          SUCCESS(0, "ok"),
          PARAMS_ERROR(40000, "请求参数错误"),
          NOT_LOGIN_ERROR(40100, "未登录"),
          NO_AUTH_ERROR(40101, "无权限"),
          NOT_FOUND_ERROR(40400, "请求数据不存在"),
          SYSTEM_ERROR(50000, "系统内部异常"),
          OPERATION_ERROR(50001, "操作失败");
      
          /**
           * 错误信息
           */
          private final String message;
      
          /**
           * 状态码
           */
          private final int code;
      
          ErrorCode(int code, String message) {
              this.message = message;
              this.code = code;
          }
      
          public String getMessage() {
              return message;
          }
      
          public int getCode() {
              return code;
          }
      }
      
    2. 通用的异常返回类

      // 在返回的类型中 数据data的响应是一个泛型
      public class BaseResponse<T> implements Serializable {
      
          private static final long serialVersionUID = -3209965291812271422L;
      
          // 异常详细信息
          private String message;
      
          // 异常编码
          private int code;
      
          // 异常数据  泛型
          private T data;
      
          public BaseResponse(int code, T data, String message) {
              this.code = code;
              this.data = data;
              this.message = message;
          }
      
          // 不传错误信息的构造方法
          public BaseResponse(int code, T data) {
              this(code, data, "");
          }
      
          // 通过枚举类来作为异常参数传入
          public BaseResponse(ErrorCode errorCode) {
              this(errorCode.getCode(), null, errorCode.getMessage());
          }
      }
      
    3. 返回工具类

      public class ResultUtils {
          /**
           * 成功的返回   需要使用泛型进行数据的返回
           * @param data
           * @return
           * @param <T>
           */
          public static <T> BaseResponse<T> success(T data) {
              return new BaseResponse(0, data, "ok");
          }
      
          /**
           * 失败的返回 使用自定义错误码
           * @param errorCode
           * @return
           */
          public static BaseResponse error(ErrorCode errorCode) {
              return new BaseResponse(errorCode.getCode(), null, errorCode.getMessage());
          }
      
          /**
           * 失败的返回  没有使用自定义错误码  自定义的异常信息 + 错误码
           * @param code
           * @param message
           * @return
           */
          public static BaseResponse error(int code, String message) {
              return new BaseResponse(code, null, message);
          }
      
          /**
           * 自定义错误码 + 自定义的异常信息
           * @param errorCode
           * @param message
           * @return
           */
          public static BaseResponse error(ErrorCode errorCode, String message) {
              return new BaseResponse(errorCode.getCode(), null, message);
          }
      }
      
    4. 基础的异常类来继承运行时异常(实现全局异常处理)

      public class BusinessException extends RuntimeException {
      
          /**
           * 错误码
           */
          private final int code;
      
          /**
           * 错误码和错误信息的构造方法
           * @param code
           * @param message
           */
          public BusinessException(int code, String message) {
              super(message);
              this.code = code;
          }
      
          /**
           * 通过传入的自定义错误码
           */
          public BusinessException(ErrorCode errorCode) {
              super(errorCode.getMessage());
              this.code = errorCode.getCode();
          }
      
          /**
           * 自定义错误码 + 自定义异常消息
           * @param errorCode
           * @param message
           */
          public BusinessException(ErrorCode errorCode, String message) {
              super(message);
              this.code = errorCode.getCode();
          }
      
          public int getCode() {
              return code;
          }
      }
      
      
    5. 全局异常处理器

      @RestControllerAdvice // 实现bean注入
      @Slf4j
      
      /**
       * 全局异常处理器
       */
      public class GlobalExceptionHandler {
      
          /**
           * 自定义的异常
           * @param e
           * @return
           */
          @ExceptionHandler(BusinessException.class)
          public BaseResponse<?> businessExceptionHandler(BusinessException e) {
              log.error("BusinessException: ", e);
              return ResultUtils.error(e.getCode(), e.getMessage());
          }
      
          /**
           * 运行时异常  系统异常
           * @param e
           * @return
           */
          @ExceptionHandler(RuntimeException.class)
          public BaseResponse<?> runtimeExceptionHandler(RuntimeException e) {
              log.error("RuntimeException: ", e);
              return ResultUtils.error(ErrorCode.SYSTEM_ERROR, "系统错误");
          }
      }
      
      

      至此一个全局异常的处理我们就实现了,能够在后续的代码编写中方便的返回我们的数据并且规范

3. 具体使用

在正确的返回,最终结果的返回的时候我们只需要使用异常工具类调用其中的成功的响应方法即可;失败的返回我们需要通过抛出异常的形式进行返回,然后全局异常处理器就能捕获到异常并输出。

 @PostMapping("/register")
	// 这里使用通用的异常类的类型
    public BaseResponse<Long> userRegister(@RequestBody UserRegisterRequest userLoginRequest) {
        if(userLoginRequest == null) {
            // 这里通过基础异常类来进行返回它继承的是运行时异常会被全局异常处理器捕获到
            // 传入的参数就是我们自定义的错误码(枚举)
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String userAccount = userLoginRequest.getUserAccount();
        String userPassword = userLoginRequest.getUserPassword();
        String checkPassword = userLoginRequest.getCheckPassword();
        if(StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        long result = userService.userRegister(userAccount, userPassword, checkPassword);
        // 成功的返回 使用异常工具类
        return ResultUtils.success(result);
    }

我们在使用在线接口文档进行测试的时候就能看到返回的数据是我们想要的格式

image-20240614165426295

总结:

​ 到这里整个异常类的统一处理就实现了,我们可以将这段代码自己保留下来然后直接复制到其他的项目上复用,这样你距离cv工程师又又又近了一步。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java:自定义注解,并使用【ImportBeanDefinitionRegistrar】动态加载

# 项目代码资源&#xff1a; 可能还在审核中&#xff0c;请等等。。。 https://download.csdn.net/download/chenhz2284/89432848 # 主项目 【pom.xml】 <groupId>com.chz</groupId> <artifactId>chzopen_study</artifactId> <packaging>pom…

嵌入式操作系统_4.任务管理

1.任务的概念 任务管理是嵌入式操作系统最基本功能之一&#xff0c;这里的任务&#xff08;task&#xff09;是指嵌入式操作系统调度的最小单位&#xff0c;类似于一般操作系统进程或线程的概念。任务是运行中的一个程序&#xff0c;一个程序加载到内存后就变成任务&#xff1…

InnoDB和MyISAM有什么区别?

InnoDB和MyISAM是MySQL中比较常用的两个执行引擎&#xff0c;MySQL在 5.5 之前版本默认存储引擎是 MyISAM,5.5 之后版本默认存储引擎是 InnoDB&#xff0c;MYISAM适合查询以及插入为主的应用&#xff0c;InnoDB适合频繁修改以及涉及到安全性较高的应用。 如果应用需要高度的数…

如果给电商系统颜值搞排名,我觉得淘宝千牛系统是天花板了。

淘宝的商家操作界面-千牛系统经过多年的迭代&#xff0c;无论从颜值上、功能上还是用户体验上都是行业天花板的存在&#xff0c;我截图软件上的一些图给大家分享下。

AirPlay技术规范及认证资讯

AirPlay是Apple开发的一种无线技术&#xff0c;允许用户将音频、视频或图片从iOS设备、Mac电脑或其他支持AirPlay的设备无线传输到支持AirPlay的接收器设备上&#xff0c;例如智能电视或音响系统。这项技术基于Wi-Fi网络&#xff0c;提供了一种便捷的方式来共享媒体内容。AirPl…

模型 POA行动

说明&#xff1a;系列文章 分享 模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。让目标凝聚伙伴&#xff0c;伙伴共创方法&#xff0c;加速实现愿景&#xff0c;可谓是行动力的“飞轮效应”。 1 POA行动模型的应用 1.1 POA模型在非营利组织&#xff08;NGO&#x…

算法day31

第一题 542. 01 矩阵 本题本来求解的是每一个1到0的最短距离并返回到矩阵之中&#xff1b; 我们采用正难则反的思路&#xff0c;将其化解为每一个0到每一个1的最短距离&#xff0c;并通过矩阵来返回&#xff1b; 解法&#xff1a;多源bfs正难则反 步骤一&#xff1a; 定义一个…

PDF标准详解(三)—— PDF坐标系统和坐标变换

之前我们了解了PDF文档的基本结构&#xff0c;并且展示了一个简单的hello world。这个hello world 虽然只在页面中显示一个hello world 文字&#xff0c;但是包含的内容却是不少。这次我们仍然以它为切入点&#xff0c;来了解PDF的坐标系统以及坐标变换的相关知识 图形学中二维…

利用Cesium和JS实现地点点聚合功能

引言 在实现基于地图的业务场景时&#xff0c;当地图上需要展示过多的标记点时&#xff0c;大量的分散点会使地图上显得杂乱无章&#xff0c;导致标记点对地图上的其他重要信息造成遮挡和混淆&#xff0c;降低地图整体的可读性。 标记点的聚合就很好的解决了这些痛点的同时&a…

线性规划问题——单纯形算法

第一步&#xff1a;化“约束标准型” 在每个等式约束中至少有一个变量的系数为正&#xff0c;且这个变量只在该约束中出现。在每个约束方程中选择一个这样的变量称为基本变量。 剩下变量称为非基本变量。 一个简单的栗子 上图是一个约束标准型线性规划的例子。 等式1&#x…

几款让你怦然心动的神奇工具——搜嗖工具箱

alteredqualia AlteredQualia 脑洞爆炸器网站&#xff0c;不得不说这是一个神奇的网站&#xff0c;在这个网站上你可以实现不可思议的各种操作&#xff0c;让我们对网站有了新的认知&#xff0c;因为它告诉你不是所有有趣的网站都那么花哨&#xff0c;有些网站看着外形平淡无奇…

AI实践与学习5-AI解题场景RAG应用预研demo

背景 AI解题场景现状&#xff0c;教研测评文档&#xff1a;xxx 解题正确率仍需进一步提高&#xff0c;提示词优化方案基本无力o目前配置的易错题CoT示例支持的长度有限&#xff0c;后续题量大的时候配置具有局限性。某些英语翻译题型BAD CASE反映大模型的输出格式不太符合要求…

设置sqlserver management的字体大小

在用sqlserver management的时候&#xff0c;总感觉怪怪的&#xff0c;然后发现是字体太小的原因。 1&#xff09;设置一下字体&#xff0c;工具--选项&#xff1a; 2&#xff09;环境--字体和颜色--显示其设置&#xff08;环境&#xff09; 3&#xff09;选择微软雅黑&#xf…

在Kubernetes中部署Elasticsearch高可用集群详细教程

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

btrace:binder_transaction+eBPF+Golang实现通用的Android APP动态行为追踪工具

一、简介&#xff1a; 在进行Android恶意APP检测时&#xff0c;需要进行自动化的行为分析&#xff0c;一般至少包括行为采集和行为分析两个模块。其中&#xff0c;行为分析有基于规则、基于机器学习、基于深度学习甚至基于大模型的方案&#xff0c;各有各的优缺点&#xff0c;不…

Photoshop中颜色与色调的调整

Photoshop中颜色与色调的调整 Photoshop中的颜色模式RGB模式灰度模式位图模式索引模式CMYK模式Lab模式 Photoshop中的颜色/色调调整命令颜色/色调调整命令的分类亮度/对比度调整命令色阶命令曲线命令曝光度命令自然饱和度命令色相/饱和度命令色彩平衡命令照片滤镜调整命令通道混…

一篇文章教你学会公众号IP写作(新手小白必备)

最近在带大家玩公众号 IP 写作&#xff0c;很多新手小白常问的问题&#xff0c; 1 什么是IP写作&#xff1f; “IP写作&#xff0c;简单来说&#xff0c;就是通过在公众号上持续写出有价值的文章&#xff0c;来建立个人影响力。 让读者了解你、信任你、找你付费。实现高价值、强…

MySQL之优化服务器设置(二)

优化服务器设置 InnoDB事务日志(包含:Redo log 重做日志和Undo log回滚日志) 了解清楚"把日志缓冲写到日中文件"和"把日志刷新到持久化存储"之间的不同是很重要的。在大部分操作系统中&#xff0c;把缓冲写到日志只是简单地把数据从InnoDB的内存缓冲转移…

MySQL中的正排/倒排索引和DoubleWriteBuffer

正排/倒排索引 正排索引 文档1&#xff1a;词条A&#xff0c;词条B&#xff0c;词条C 文档2&#xff1a;词条A&#xff0c;词条D 文档3&#xff1a;词条B&#xff0c;词条C&#xff0c;词条E正排表是以文档的ID为关键字&#xff0c;表中记录文档中的每个字的位置信息&#xff…

人事信息管理系统(Java+MySQL)

一、项目背景 在现代企业中&#xff0c;管理大量员工的工作信息、薪资、请假、离职等事务是一项非常繁琐和复杂的任务。传统的手工管理方式不仅效率低下&#xff0c;而且容易出错。为了提高人事管理的效率&#xff0c;减少人工操作带来的错误&#xff0c;企业迫切需要一个高效…