首页 > 其他分享 >SpringBoot定义优雅全局统一Restful API 响应框架

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

时间:2023-05-02 17:32:12浏览次数:34  
标签:code return SpringBoot success private API message Restful public

假如现在有一个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对象返回。

这个时候该如何处理

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

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

标签:code,return,SpringBoot,success,private,API,message,Restful,public
From: https://blog.51cto.com/u_15293798/6240067

相关文章

  • SpringBoot定义优雅全局统一Restful API 响应框架
    假如现在有一个Java项目,老板让你做项目组长,定义项目基础框架,系统技术架构选型,你应该如何设计一个规范的统一的RestfulAPI响应框架呢思考目前项目开发,都是基于前后端分离模式开发的,基于后端模板引擎那一套,可能已经不适用一些项目开发流程,和当下开发模式了,尤其在要写......
  • SpringBoot:如何使用不同环境的配置信息?
    一、准备不同环境的配置文件通用:application.yml一定会被使用的配置信息,存放通用的配置。#通用配置server:port:8080生产环境:application-prod.yml存放生产环境的配置信息,如生产数据库的连接配置。#生产环境,配置数据库连接信息spring:datasource:d......
  • 理解 Java8 的时间API(二)时间
    理解Java8的时间API:java.time上一篇介绍了Java8里新的时区API。这一篇介绍新的时间API:LocalDateTime,LocalDate,LocalTime类。三、Java8中的时间最常用的应该是java.time.LocalDateTime,java.time.LocalDate,java.time.LocalTime,java.time.Instant这几个类。3.1LocalDateTim......
  • springboot常用注解
    ......
  • springboot 静态资源导入
    1.根据源码可以看到需要去webjars官网下载jquery的依赖<dependency><groupId>org.webjars</groupId><artifactId>jquery</artifactId><version>2.2.4</version></dependency>2.读源码 总结: 1.在springboot中可以使用以下五种方式处理静态资源:we......
  • 手机操作API
    目录手机操作API获取手机分辨率手机截图获取和设置手机网络发送键到设备操作手机通知栏总结手机操作API获取手机分辨率应用场景自动化测试可能会需要根据当前设备的屏幕分辨率来计算一些点击或者滑动的坐标核心代码#获取手机分辨率print(driver.get_window_size())执行结......
  • SpringBoot高频面试题
    Springboot的优点内置servlet容器,不需要在服务器部署tomcat。只需要将项目打成jar包,使用java-jarxxx.jar一键式启动项目SpringBoot提供了starter,把常用库聚合在一起,简化复杂的环境配置,快速搭建spring应用环境可以快速创建独立运行的spring项目,集成主流框架准生产环境的......
  • Java教程:Springboot项目如何使用Test单元测试
    今天早上来公司领导突然分配了任务,就是简单的测试一下实体的添加修改功能,要使用到Juntil单元测试,目前使用springboot项目,jpa,maven管理,回忆起曾经用到过@Test注解,于是开始唰唰唰的写起了测试咧,然鹅,一顿报错,依赖无法注入,空指针,乱七八糟的一大通,无奈开始借助百度,终于实现了单元测试,......
  • SpringBoot项目使用 validation进行数据校验
    validation进行数据校验@Validated注解和@Valid注解都是SpringFramework中用于数据校验的注解,但它们有以下几点区别:所在包路径不同:@Valid注解位于javax.validation.constraints包下,而@Validated注解位于org.springframework.validation.annotation包下。支持......
  • Springboot @Test 给Controller接口 写 单元测试
    Springboot@Test给Controller接口写单元测试https://blog.csdn.net/qq_35387940/article/details/129140984?spm=1001.2101.3001.6650.8&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-8-129140984-blog-103569814.235%5Ev32......