SpringBoot定义优雅全局统一Restful API 响应框架

news2024/10/7 6:39:54

假如现在有一个Java项目,老板让你做项目组长,定义项目基础框架,系统技术架构选型,
你应该如何设计一个规范的统一的Restful API 响应框架呢

思考

目前项目开发,都是基于前后端分离模式开发的,基于后端模板引擎那一套,可能已经不适用一些项目开发流程,和当下开发模式了,尤其在要写比较大型项目,前后端项目拆分,团队共同开发那是必不可少的

目前的前后端开发大部分数据的传输格式都是json,因此定义一个统一规范的数据格式有利于前后端的交互与UI的展示。

返回的统一接口形式应该包含这些内容

  1. 是否响应成功
  2. 响应状态码
  3. 状态码描述
  4. 响应数据
  5. 接口调用时间
  6. 其他标识符

按照这些我们可以定义统一的标准结果返回

响应枚举

前三者可以定义为 success,code,message

package cn.soboys.springbootrestfulapi.common.resp;

import lombok.Data;
import lombok.Getter;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/4/28 22:39
 * @webSite https://github.com/coder-amiao
 * 响应结果枚举
 */
@Getter
public enum ResultCodeEnum{
    SUCCESS(true, 200, "成功"),
    FAIL(false, 400, "请求失败"),

    NOT_FOUND(false, 404, "接口不存在"),
    FORBIDDEN(false, 403, "资源拒绝访问"),
    UNAUTHORIZED(false, 401, "未认证(签名错误)"),

    INTERNAL_SERVER_ERROR(false, 500, "服务器内部错误"),


    NULL_POINT(false, 200002, "空指针异常"),
    PARAM_ERROR(false, 200001, "参数错误");

    /**
     * 响应是否成功
     */
    private Boolean success;
    /**
     * 响应状态码
     */
    private Integer code;
    /**
     * 响应信息
     */
    private String message;


    ResultCodeEnum(Boolean success, Integer code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;
    }
}

统一结果类

  • 外部返回调用类统一的结果方法 success,failure 因此构造器私有
  • 内置静态方法,直接返回对象
  • 便于自定义统一结果信息,使用链式编程,返回对象类本身 return this
  • 响应数据为json格式,可定义为JsonObjectMap形式
package cn.soboys.springbootrestfulapi.common.resp;

import lombok.Data;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/4/28 22:47
 * @webSite https://github.com/coder-amiao
 * 统一响应结果处理  使用链式编程 返回类本身
 */
@Data
public class R {

    private Boolean success;

    private Integer code;

    private String message;

    /**
     * 接口请求时间戳
     */
    private Long timestamp;

    private Map<String, Object> data = new HashMap<>();


    private R setSuccess(Boolean success) {
        this.success = success;
        return this;
    }


    private R setMessage(String message) {
        this.message = message;
        return this;
    }

    private R setData(Map<String, Object> data) {
        this.data = data;
        return this;
    }

    private R setCode(Integer code) {
        this.code = code;
        return this;
    }

    private R() {
    }

    private R(Long timestamp) {
        this.timestamp = timestamp;
    }


    /**
     * 通用返回成功
     *
     * @return
     */
    public static R success() {
        return new R(System.currentTimeMillis())
                .setSuccess(ResultCodeEnum.SUCCESS.getSuccess())
                .setCode(ResultCodeEnum.SUCCESS.getCode())
                .setMessage(ResultCodeEnum.SUCCESS.getMessage());

    }

    /**
     * 通用返回失败
     *
     * @return
     */
    public static R failure() {
        return new R(System.currentTimeMillis())
                .setSuccess(ResultCodeEnum.FAIL.getSuccess())
                .setCode(ResultCodeEnum.FAIL.getCode())
                .setMessage(ResultCodeEnum.FAIL.getMessage());

    }

    /**
     * 设置结果,形参为结果枚举
     *
     * @param result
     * @return
     */
    public static R setResult(ResultCodeEnum result) {
        return new R(System.currentTimeMillis())
                .setSuccess(result.getSuccess())
                .setCode(result.getCode())
                .setMessage(result.getMessage());

    }


    // 自定义返回数据
    public R data(Map<String, Object> map) {
        return this.setData(map);

    }

    // 通用设置data
    public R data(String key, Object value) {
        this.data.put(key, value);
        return this;
    }

    // 自定义状态信息
    public R message(String message) {
        return this.setMessage(message);

    }

    // 自定义状态码
    public R code(Integer code) {
        return this.setCode(code);

    }

    // 自定义返回结果
    public R success(Boolean success) {
        return this.setSuccess(success);

    }

}

控制层调用返回

package cn.soboys.springbootrestfulapi.controller;


import cn.soboys.springbootrestfulapi.common.resp.R;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/4/28 23:58
 * @webSite https://github.com/coder-amiao
 */
@RestController
public class IndexController {

    @GetMapping("/index")
    public R index() {
        Map m = new HashMap();
        m.put("name", "Tom");
        m.put("age", 25);
        m.put("sex", "男");
        return R.success().data(m);
    }

    @GetMapping("/home")
    public R home() {

        Student s = new Student();
        s.setUserName("Tom");
        s.setBalance(2229891.0892);
        return R.success().data("user", s).message("查询用户详情信息");
    }

    /**
     * 异常返回模拟
     *
     * @return
     */
    @GetMapping("/exception")
    public R exception() {
        Map m = null;
        m.put("name", "Jack");
        return R.success().data("user", m).message("查询用户详情信息");
    }
}

统一结果类的使用参考了mybatis-plus中R对象的设计。

问题思考

使用统一返回结果时,还有一种情况,就是程序由于运行时异常导致的结果,有些异常我们可

能无法提前预知,不能正常走到我们return的R对象返回。

这个时候该如何处理

下一篇文章会继续分享,留下你的思考

准备从零做一套自己的开发脚手架模板 ,关注公众 程序员三时

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

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

相关文章

(五)Spring源码阅读:invokeBeanFactoryPostProcessors方法

一、概述 invokeBeanFactoryPostProcessors的执行顺序大致如下&#xff0c;先执行子类BeanDefinitionRegistryPostProcessor再执行父类BeanFactoryPostProcessor。而对于同一个类的执行顺序是先执行外部的集合再到子集&#xff0c;之后再到父集。更小维度执行的顺序按照order注…

WebSocket的那些事(1-概念篇)

目录 一、什么是Websocket二、WebSocket部分header介绍三、HTTP VS WebSocket四、什么时候使用WebSockets五、关于SockJS和STOMP 一、什么是Websocket 根据 RFC 6455 标准&#xff0c;Websocket协议提供了一种标准化的方式在客户端和服务端之间通过TCP连接建立全双工、双向通信…

【DarkLabel】使用教程(标注MOT数据集)

DarkLabel 使用教程 功能部分 Open video 第 2 处的内容为数据集类型。例如&#xff1a;VOC、COCO、MOT、YOLO等。 第 3 处的内容为标签名称。 可在 darklabel.yml 中修改 classes_set。例如&#xff1a;classes_set: "mot_classes" 第 4 处的内容为两种跟踪方法…

Maven项目的配置

Maven是什么&#xff1f;它的作用是什么&#xff1f; Maven是一种开源的构建工具&#xff0c;它可以自动化构建、测试、部署和管理Java项目。它提供了一个中心化的构建过程&#xff0c;包括依赖管理、项目结构管理、插件管理等&#xff0c;使得开发人员更方便地维护和协作应用…

【Python】操作MySQL

一、Python 操作 Mysql的方式 Python 操作 Mysql 主要包含下面 3 种方式&#xff1a; Python-MySql Python-MySql 由 C 语法打造&#xff0c;接口精炼&#xff0c;性能最棒&#xff1b;但是由于环境依赖多&#xff0c;安装复杂&#xff0c;已停止更新&#xff0c;仅支持 Python…

记一次我的漏洞挖掘实战——某公司的SQL注入漏洞

目录 一、前言 二、挖掘过程 1.谷歌语法随机搜索 2.进入网站 3.注入点检测 3.SQLMAP爆破 &#xff08;1&#xff09;爆库 &#xff08;2&#xff09;爆表 &#xff08;3&#xff09;爆字段 三、总结 一、前言 我是在漏洞盒子上提交的漏洞&#xff0c;上面有一个项目叫…

【远程工具】- Tabby 下载、安装、使用、配置【ssh/Serial】-免安装、解压即用

目录 一、Tabby 概述 二、Tabby 下载、安装 三、Tabby 的使用  &#x1f449;3.1 使用SSH协议连接Linux开发主机  &#x1f449;3.2 使用Serial(串口)协议连接开发板 一、Tabby 概述 在远程终端工具中&#xff0c;secureCrt 和 XShell 是两款比较有名的远程工具&#xff0c;但…

矩阵求逆方法

1.待定系数法 矩阵A 1, 2 -1,-3 假设所求的逆矩阵为 a,b c,d 则 从而可以得出方程组 a 2c 1 b 2d 0 -a - 3c 0 -b - 3d 1 解得 a3; b2; c -1; d -1 2.伴随矩阵求逆矩阵 伴随矩阵是矩阵元素所对应的代数余子式&#xff0c;所构成的矩阵&#xff0c;转置后得到的新矩阵…

图的存储--邻接矩阵/边集数组/邻接表/链式邻接表/链式前向星

邻接矩阵 使用二维数组w[u][v]存储点u到点v的边的权值。一般应用在点数不多的稠密图 时间复杂度&#xff1a;O(n2) 空间复杂度&#xff1a;O(n2) int w[N][N]; // edge int vis[N]; // visitedvoid dfs(int u){vis[u] true;for(int v 1; v < n; v)if(w[u][v]){prin…

Java 基础进阶篇(六)—— 面向对象三大特征之三:多态

文章目录 一、多态的概述二、多态中成员访问特点 ★三、多态的优势与劣势四、多态下的类型转换4.2 自动类型转换&#xff08;从子到父&#xff09;4.2 强制类型转换&#xff08;从父到子&#xff09;4.3 instanceof 关键字 一、多态的概述 多态&#xff1a;是指执行同一个行为…

自动驾驶——最优控制算法里卡提方程推导【连续系统】

1. Why use the Riccati equation&#xff1f; Q、R就是需要设计的半正定矩阵和正定矩阵。考虑根据实车的情况去标定此参数&#xff0c;从理论和工程层面去理解&#xff0c;如果增大Q、减小R&#xff0c;则此时控制系统响应速度比较快速&#xff08;比较剧烈&#xff09;&…

[SpringBoot]什么是服务器前后端的一个流程图bmi练习案例

前点: 服务器&#xff1a; 服务器就是一台高性能的电脑, 在电脑上安装了提供XXX服务的软件, 这台电脑就可以称为XXX服务器 - 举例: - 数据库服务器: 在电脑上安装了提供数据增删改查服务的软件(DBMS) - 邮件服务器: 在电脑上安装了提供邮件收发服务的软件 - FTP服务器: …

普通的2D Average pooling是怎么进行backward的呢?

二维平均池层计算损失相对于其输入张量的梯度&#xff0c;方法是将损失相对于输出张量的梯度均分在输入子区域&#xff0c;这些子区域在前向传播中被用来计算平均值。 由于平均集合计算的是每个输入子区域的平均值&#xff0c;所以子区域中的每个元素对平均值的贡献是相同的。…

Java Servlet_HTTP

今日内容 零、 复习昨日 一、Servlet 二、HTTP 三、HttpServlet 零、 复习昨日 见晨考 一、Servlet 1.1 介绍 javaweb开发,就是需要服务器接收前端发送的请求,以及请求中的数据,经过处理(jdbc操作),然后向浏览器做出响应. 我们要想在服务器中写java代码来接收请求,做出响应,我…

SignOff Criteria——AOCV(Advanced OCV) introduction

文章目录 1. O v e r v i e w Overview Overview2. A O C V P r i n c i p l e I n t r o d u c t i o n AOCV\ Principle\ Introduction AOCV Principle Introduction2.1 G B A − A O C V GBA-AOCV GBA−AOCV2.1.1 A b o u t L o g i c a l D e p t h About\ Logical\ De…

第六章 Iptables与Firewalld防火墙

第六章 Iptables与Firewalld防火墙 一、Iptables 1、策略与规则链 &#xff08;1&#xff09;、防火墙策略规则的设置 一种是“通”即放行&#xff0c;另一种是“堵”即阻止。 当防火墙的默认策略为拒绝时&#xff08;堵&#xff09;&#xff0c;就要设置允许规则通&#x…

NECCS|全国大学生英语竞赛C类|听力|短对话|14:20~15:30

目录 一、短对话 1. 定位词 2. 场景词汇 &#xff08;1&#xff09;餐馆用餐 &#xff08;2&#xff09;商场用语 &#xff08;3&#xff09;校园用语 &#xff08;4&#xff09;图书馆用语 二、题目类型 1. 人物类 考点聚焦 2. 地点类 主要涉及 3. 数字类 4. 主题…

【数据库】JDBC编程

前言 小亭子正在努力的学习编程&#xff0c;接下来将开启javaEE的学习~~ 分享的文章都是学习的笔记和感悟&#xff0c;如有不妥之处希望大佬们批评指正~~ 同时如果本文对你有帮助的话&#xff0c;烦请点赞关注支持一波, 感激不尽~~ 目录 前言 什么是JDBC&#xff1f; JDBC工…

sql注入(三)绕过方法及防御手段

一、sql注入的绕过方法 1.注释符过滤绕过 常用的注释符有&#xff1a; 1&#xff09;-- 注释内容 2&#xff09;# 注释内容 3&#xff09;/* 注释内容 */ 绕过方法 构造闭合&#xff1a; ?id1 and sql语句 and 11 这样接收源码前面的引号被 id1 中的后引号所闭合&…

关于MPU的笔记

MPU&#xff08;memory protection unit&#xff09;内存保护单元。这些系统必须提供一种机制来保证正在运行的任务不破坏其他任务的操作。即要防止系统资源和其他一些任务不受非法访问。嵌入式系统有专门的硬件来检测和限制系统资源的访问。它能保证资源的所有权&#xff0c;任…