在 Spring Boot 中构造 API 响应的最佳实践

在平时的开发和项目中,我们一定会涉及到接口对接的功能,由于不同开发人员的编码习惯不同,API报文在项目中通常是"百花齐放"的。

不但增加工作难度,往往也是扯皮的大头,如果能统一报文格式,不但能减少沟通成本,同时也可以减少并行开发的难度,今天我们就来介绍一种在项目中常用的API响应最佳实践,快快@你的同事,看完以后,下次对接我们直接“打默认”

01 / 为什么好的API报文结构很重要

  • 优化客户端的错误提示和处理逻辑,前端小姐姐看到了会请你吃饭
  • 减少调试时的工作量,可以更快的发现问题,避免加班引起严重脱发
  • 增加代码的可读性和维护性,避免code review的时候被老大骂

02 / 什么才是良好的API响应

结构良好的 API 响应应该是:

  • 一致:不同端点之间的格式一致。

  • 信息足够有效:包括相关数据、消息、状态代码和错误代码。

  • 简单:易于解析和理解。

    03 / 如何制定良好的结构

定义标准响应格式

首先创建所有 API 都将遵循的标准响应格式。这是一个简单而有效的格式:

图片

在此结构中, errorCode作为专门用于应用程序级错误的字段。需要注意的是,这并不意味着要取代标准 HTTP 状态代码,如200 OK 、 404 Not Found等。

相反,我们更推荐使用 HTTP 状态代码来维护标准协议级错误处理。

当应用程序需要处理更细粒度的、与业务相关的错误场景时, errorCode就会发挥作用。

例如,考虑用户的请求违反业务规则的情况 - 即使从语法或结构的角度来看该请求可能是有效的,但这应该导致400 Bad Request HTTP 状态,因为输入不符合应用程序的业务规则。

在这种情况下, errorCode将从业务逻辑的角度提供有关到底出了什么问题的更多详细信息。

例如,如果用户提交缺货产品的订单,系统将响应400 Bad Request状态并提供errorCode ,例如2000 (商品缺货)。

这使得 UI 或使用 API 的任何客户端能够通过显示适当的错误消息或提示用户采取特定操作(例如,“该产品不再可用”),以更明智和一致的方式处理情况。

这种方法确保HTTP 状态代码反映协议级别请求的总体结果,而errorCode提供用于处理应用程序内特定业务逻辑错误的附加信息。

它还简化了系统不同层的错误处理,因为errorCode可用于触发 UI 或使用 API 的任何其他服务中的特定操作。

每个字段解释:

success: 

  • 类型:boolean

  • 描述:指示 API 调用是否成功。

  • 功能:快速确定请求的结果,简化客户端逻辑。

message:

  • 类型: String

  • 描述:提供有关 API 调用结果的人类可读消息。

  • 功能:有助于向客户提供上下文反馈,对于成功和错误场景都很有用。

data: 

  • 类型: T

  • 描述:包含响应的有效负载,可以是任何数据类型。

  • 功能:提供客户请求的实际数据。

errors:

  • 类型:List<String>

  • 描述:API 调用不成功时的错误消息列表。

  • 功能:提供有关出错原因的详细信息,对于调试和用户反馈很有用。

errorCode:

  • 类型:int

  • 描述:表示错误类型的特定代码。

  • 功能:有助于以编程方式对错误进行分类并做出适当的响应。这是针对应用程序级别的错误,可能与任何业务流程错误相关,可能需要在 UI 层进行更多处理。所以这会很有帮助。但对于错误代码,我们应该始终优先考虑 HTTP 状态代码。

timestamp:

  • 类型: long

  • 描述:生成响应时的时间戳。

  • 功能:对于记录和跟踪响应时间很有用,这可以帮助调试和监控。

path:

  • 类型:String

  • 描述:被调用的 API 端点。

  • 功能:帮助识别哪个 API 端点生成了响应,对于调试和日志记录很有用。

04 / 创建实用的响应处理方法


public class ResponseUtil {public static <T> ApiResponse<T> success(T data, String message, String path) {ApiResponse<T> response = new ApiResponse<>();response.setSuccess(true);response.setMessage(message);response.setData(data);response.setErrors(null);response.setErrorCode(0); // No application-level error, success scenarioresponse.setTimestamp(System.currentTimeMillis());response.setPath(path);return response;}public static <T> ApiResponse<T> error(List<String> errors, String message, int errorCode, String path) {ApiResponse<T> response = new ApiResponse<>();response.setSuccess(false);response.setMessage(message);response.setData(null);response.setErrors(errors);response.setErrorCode(errorCode);  // Application-specific error coderesponse.setTimestamp(System.currentTimeMillis());response.setPath(path);return response;}public static <T> ApiResponse<T> error(String error, String message, int errorCode, String path) {return error(Arrays.asList(error), message, errorCode, path);}
}

04 / 实现全局异常处理

全局处理异常可确保捕获任何未处理的错误并以标准响应格式返回。使用@ControllerAdvice和@ExceptionHandler注释。


@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(Exception.class)public ResponseEntity<ApiResponse<Void>> handleException(HttpServletRequest request, Exception ex) {List<String> errors = Arrays.asList(ex.getMessage());ApiResponse<Void> response = ResponseUtil.error(errors, "An error occurred", 1000, return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);}@ExceptionHandler(ResourceNotFoundException.class)public ResponseEntity<ApiResponse<Void>> handleResourceNotFoundException(HttpServletRequest request, ResourceNotFoundException ex) {ApiResponse<Void> response = ResponseUtil.error(ex.getMessage(), "Resource not found", 1001, return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);}@ExceptionHandler(ValidationException.class)public ResponseEntity<ApiResponse<Void>> handleValidationException(HttpServletRequest request, ValidationException ex) {ApiResponse<Void> response = ResponseUtil.error(ex.getErrors(), "Validation failed", 1002, return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);}// Handle other specific exceptions similarly
}

05 / 在controller中使用响应格式


@RestController
@RequestMapping("/api/products")
public class ProductController {@GetMapping("/{id}")public ResponseEntity<ApiResponse<Product>> getProductById(@PathVariable Long id, HttpServletRequest request) {// Fetch product by id (dummy code)Product product = productService.findById(id);if (product == null) {throw new ResourceNotFoundException("Product not found with id " + id);}ApiResponse<Product> response = ResponseUtil.success(product, "Product fetched successfully", request.getRequestURI());// Success response, no application-level errorreturn new ResponseEntity<>(response, HttpStatus.OK);}@PostMappingpublic ResponseEntity<ApiResponse<Product>> createProduct(@RequestBody Product product, HttpServletRequest request) {// Create new product (dummy code)Product createdProduct = productService.save(product);ApiResponse<Product> response = ResponseUtil.success(createdProduct, "Product created successfully", request.getRequestURI());// Success response, no application-level errorreturn new ResponseEntity<>(response, HttpStatus.CREATED);}// More endpoints...
}

06/ 定义统一的错误代码

统一的错误代码,可以避免重复的沟通,直接记录在文档中,或者保存在统一的配置中心中,上下游需要使用的时候可以直接查阅。

同时定义错误代码的过程,也是对自己逻辑重新梳理的过程,避免在编写时遗漏了边界情况Error Code Description

2000 Item out of stock2001 Payment method declined2002 Invalid coupon code2003 Order cancellation period expired2004 Account temporarily suspended2005 Multiple orders detected for the same productmark

07 / 总结

完成了这些工作,你就得到一个近乎完美的API报文结构,它干净整洁,易于维护。同时减少了巨大的沟通成本,当然好的规范是需要团队共同执行的,多和你的同事沟通,相信你们的合作会越来越顺利的

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

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

相关文章

多目标优化算法——多目标粒子群优化算法(MOPSO)

Handling Multiple Objectives With Particle Swarm Optimization&#xff08;多目标粒子群优化算法&#xff09; 一、摘要&#xff1a; 本文提出了一种将帕累托优势引入粒子群优化算法的方法&#xff0c;使该算法能够处理具有多个目标函数的问题。与目前其他将粒子群算法扩展…

OpenCV与AI深度学习|16个含源码和数据集的计算机视觉实战项目(建议收藏!)

本文来源公众号“OpenCV与AI深度学习”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;分享&#xff5c;16个含源码和数据集的计算机视觉实战项目 本文将分享16个含源码和数据集的计算机视觉实战项目。具体包括&#xff1a; 1. 人…

Jenkins升级到最新版本后无法启动

1. 场景还原 最近在web界面将jenkins升级到最新版本后&#xff0c;后台无法启动jenkins服务&#xff0c;服务状态如下&#xff1a; 运行jenkins命令提示invalid Java version jenkins --version jenkins: invalid Java version: java version "1.8.0_202" Java(TM)…

【计算机视觉+MATLAB】自动检测并可视化圆形目标:通过 imfindcircles 和 viscircles 函数

引言 自动检测图像中的圆形或圆形对象&#xff0c;并可视化检测到的圆形。 函数详解 imfindcircles imfindcircles是MATLAB中的一个函数&#xff0c;用于在图像中检测并找出圆形区域。 基本语法&#xff1a; [centers, radii] imfindcircles(A, radiusRange) [centers, r…

鸿蒙NEXT元服务:利用App Linking实现无缝跳转与二维码拉起

【效果】 元服务链接格式&#xff08;API>12适用&#xff09;&#xff1a;https://hoas.drcn.agconnect.link/ggMRM 生成二维码后效果&#xff1a; 【参考网址】 使用App Linking实现元服务跳转&#xff1a;文档中心 草料二维码&#xff1a;草料二维码生成器 【引言】 …

下载安装Android Studio

&#xff08;一&#xff09;Android Studio下载地址 https://developer.android.google.cn/studio 滑动到 点击下载文档 打开新网页 切换到english ![](https://i-blog.csdnimg.cn/direct/b7052b434f9d4418b9d56c66cdd59fae.png 等待一会&#xff0c;出现 点同意后&#xff0…

【C/C++】深入解析 Stack 与 Queue 数据结构(详解):实现原理、应用场景与性能优化

文章目录 引言栈&#xff08;Stack&#xff09;数据结构详解1. 栈的基本概念2. 栈的实现原理3. C中的栈实现4. 栈的应用场景5. 栈的性能分析6. 实战示例&#xff1a;括号匹配 队列&#xff08;Queue&#xff09;数据结构详解1. 队列的基本概念2. 队列的实现原理3. C中的队列实现…

【css实现收货地址下边的平行四边形彩色线条】

废话不多说&#xff0c;直接上代码&#xff1a; <div class"address-block" ><!-- 其他内容... --><div class"checked-ar"></div> </div> .address-block{height:120px;position: relative;overflow: hidden;width: 500p…

从零开始配置Qt+VsCode环境

从零开始配置QtVsCode环境 文章目录 从零开始配置QtVsCode环境写在前面扩展安装及配置Qt Configure配置 VsCode创建Qt工程VsCodeQMakeMinGwVsCodeQMakeMsvcVsCodeCMakeMinGwVsCodeCMakeMsvcQtCreatorQMakeMinGw->VsCodeQtCreatorQMakeMsvc->VsCodeQtCreatorCMakeMinGw-&g…

【前端】JavaScript中的字面量概念与应用详解

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端 文章目录 &#x1f4af;前言&#x1f4af;字面量1. 数字字面量2. 字符串字面量3. 布尔字面量4. 空值字面量&#xff08;null&#xff09;5. 对象字面量6. 数组字面量7. 正则表达式字面量8. 特殊值字面量9. 函数字…

Python使用ffmpeg进行本地视频拉流,并使用训练模型识别人脸,并将识别后的模型推流源码

前言&#xff1a; Windows上搭建nginx-rtsp流媒体服务器&#xff0c;实现FFmpeg推流、录像转rtsp推流 - WayWayWayne - 博客园参考上述文章和一些webRTC前端拉流文章 主要是缕一缕思路和每个部分的代码功能&#xff0c;文件命名高度相似导致。 效果&#xff1a; 代码&#x…

【去毛刺】OpenCV图像处理基础:腐蚀与膨胀操作入门

在数字图像处理中&#xff0c;形态学操作是一种常用的技术&#xff0c;用于提取图像中的特定形状或特征。其中&#xff0c;腐蚀&#xff08;Erosion&#xff09;和膨胀&#xff08;Dilation&#xff09;是两种基本的形态学运算。本文将通过一个简单的例子来演示如何使用Python中…

2024年11月27日Github流行趋势

项目名称&#xff1a;screenshot-to-code 项目维护者&#xff1a;abi clean99 sweep-ai kachbit vagusX项目介绍&#xff1a;通过上传截图将其转换为整洁的代码&#xff08;支持HTML/Tailwind/React/Vue&#xff09;。项目star数&#xff1a;62,429项目fork数&#xff1a;7,614…

Linux八股积累与笔记

1、iptables 是一个用于配置Linux内核防火墙规则的工具。四表五链&#xff1a;在iptables中&#xff0c;有四个表&#xff08;tables&#xff09;和五个链&#xff08;chains&#xff09;&#xff0c;用于管理不同类型的数据包过滤规则。如下&#xff1a; 表&#xff08;Tabl…

Qt5.14.2的安装与环境变量及一些依赖库的配置

目录 1.Qt5.14.2安装 2.Qt环境变量及一些依赖库的配置 1.Qt5.14.2安装 QT从入门到入土&#xff08;一&#xff09;——Qt5.14.2安装教程和VS2019环境配置 - 唯有自己强大 - 博客园 2.Qt环境变量及一些依赖库的配置 假设QT安装目录为: D:\Qt\Qt5.14.2 将目录: D:\Qt\Qt5.14.…

初识Linux(4):Linux基础环境工具(下)

1. Git Git是一种版本控制系统&#xff0c;是一种工具&#xff0c;用于代码的存储和版本控制。 而我们常见的Gitee和Gitehub都是基于Git&#xff08;Git是开源的&#xff09;实现的在线代码仓库&#xff0c;而前者服务器位于中国&#xff0c;后者服务器位于美国。 总的来说&…

12.Three.js纹理动画与动效墙案例

12.Three.js纹理动画与动效墙案例 在Three.js的数字孪生场景应用中&#xff0c;我们通常会使用到一些动画渲染效果&#xff0c;如动效墙&#xff0c;飞线、雷达等等&#xff0c;今天主要了解一下其中一种动画渲染效果&#xff1a;纹理动画。下面实现以下动效墙效果&#xff08…

《白帽子讲Web安全》13-14章

《白帽子讲Web安全》13-14章 《白帽子讲Web安全》13-14章13、应用层拒绝服务攻击13.1、DDOS简介13.2、应用层DDOS13.2.1、CC攻击13.2.2、限制请求频率13.2.3、道高一尺&#xff0c;魔高一丈 13.3、验证码的那些事儿13.4、防御应用层DDOS13.5、资源耗尽攻击13.5.1、Slowloris攻击…

【电子元器件】Nand Flash基础介绍

本文章是笔者理论结合实践进行整理的备忘笔记。希望在帮助自己温习避免遗忘的同时&#xff0c;也能帮助其他需要参考的朋友。如有谬误&#xff0c;欢迎大家进行指正。 一、什么是Nand Flash Flash主要分两种&#xff0c;Nand Flash和Nor flash。 Nor的成本相对高&#xff0c…

JVM_垃圾收集器详解

1、 前言 JVM就是Java虚拟机&#xff0c;说白了就是为了屏蔽底层操作系统的不一致而设计出来的一个虚拟机&#xff0c;让用户更加专注上层&#xff0c;而不用在乎下层的一个产品。这就是JVM的跨平台&#xff0c;一次编译&#xff0c;到处运行。 而JVM中的核心功能其实就是自动…