【SpringBoot Web框架实战教程】04 SpringBoot 规范统一输出 json

不积跬步,无以至千里;不积小流,无以成江海。大家好,我是闲鹤,微信:xxh_1459,十多年开发、架构经验,先后在华为、迅雷服役过,也在高校从事教学3年;目前已创业了7年多,主要从事物联网/车联网相关领域和业务。喜欢交友、骑行、写毛笔字、弹吉他、折腾硬件和写代码。


导读

这是一系列关于 SpringBoot Web框架实战 的教程,从项目的创建,到一个完整的 web 框架(包括异常处理、拦截器、context 上下文等);从0开始,到一个可以直接运用在生产环境中的web框架,所有源码均开源。


正文

我们写的 Spring Boot 这一系列文章,是以最终开发一个web api项目为目标,根据开发所需,逐步来学习和撰写的。比如:

由于我们的目标是开发一个提供 api json 接口访问的 web server,一般情况下,对于统一对外的 api json 接口,都有一定的格式规范,比如类似以下格式:

{
    code: 200,
    msg: "success",
    data: {}
}

所以,这篇,我们先把一个基本的 Rest api 框架的统一规范输出给设计好。

创建返回的数据结构

我们以上面的格式为我们所需要的返回数据格式,可以看出,这里基本有3个字段:

字段类型含义
codeInt返回码
msgString文本描述
dataObject/Array返回的具体数据
  • code:可以定义为一系列常量

  • msg:为 code 对应的具体的描述,如果需要兼容其他语种的话,可以增加对其他语种的支持,这里我们先仅处理中文

  • data:为具体的返回数据,它的类型可以为对象,也可以为列表,在设计时,我们可以采用泛型来处理

我们把这个数据结构,定义为bean,所以我们先在我们项目中创建 beans 包,然后在该包里创建 RtData.java:

package com.jdz.beans;

public class RtData<T> {
    private Integer code;
    private String msg;
    private T data;

    public RtData() {
        this.code = ErrType.SUCCESS;
        this.msg = ErrType.getDesc(this.code);
        this.data = (T) new Object();
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
        this.msg = ErrType.getDesc(this.code);
    }

    public String getMsg() {
        return msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

说明 在构造函数中,对 code 取默认值 msg 的值是取决于 code 值的,所以 msg 不对外进行 setter

code 为常量,并且需要与 msg 进行映射,因此我们定义 ErrType 类型:

package com.jdz.beans;

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

public class ErrType {
    public static final Integer SUCCESS                 =       200;    // 成功
    public static final Integer ERR_PARAMS              =       100;    // 参数错误
    public static final Integer ERR_ACCESS              =       101;    // 访问失败
    public static final Integer ERR_NOT_PRIVILEGE       =       102;    // 没有权限

    public static final Integer ERR_INNER               =       400;    // 内部错误

    private static final Map<Integer, String> descMap = new HashMap<Integer, String>(){
        {
            put(SUCCESS,                        "成功");
            put(ERR_PARAMS,                     "参数错误");
            put(ERR_ACCESS,                     "访问失败");
            put(ERR_NOT_PRIVILEGE,              "没有权限");
            put(ERR_INNER,                      "内部错误");
        }
    };

    public static String getDesc(Integer code) {
        String res = descMap.get(code);
        return res == null ? "未定义" : res;
    }
}

说明: 常量类型定义为 public 可以直接对外访问 code 对应的 msg ,通过 getDesc 方法获取

controller 类改写

由于我们每个 controller 返回的方式都是一致的,所以我们把返回的方法抽象出来,定义一个 controller 基类,即:

package com.jdz.controllers;

import com.jdz.beans.RtData;

public class BaseController {

    /**
     * 默认返回值
     */
    public <T> RtData<T> rtJson() {
        return new RtData<>();
    }

    /**
     * 定义 code 返回值
     */
    public <T> RtData<T> rtJson(Integer code) {
        RtData<T> rtData = new RtData<>();
        rtData.setCode(code);
        return rtData;
    }

    /**
     * 定义 data 返回值
     */
    public <T> RtData<T> rtJson(T data) {
        RtData<T> rtData = new RtData<>();
        rtData.setData(data);
        return rtData;
    }

    /**
     * 定义 code 和 data 返回值
     */
    public <T> RtData<T> rtJson(Integer code, T data) {
        RtData<T> rtData = new RtData<>();
        rtData.setCode(code);
        rtData.setData(data);
        return rtData;
    }
}

再定义我们具体的 controller 类:

package com.jdz.controllers;

import com.jdz.beans.RtData;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class IndexController extends BaseController {

    @RequestMapping("/index")
    public RtData<String> index() {
        return rtJson();
    }

    @RequestMapping("/list")
    public RtData<List<Integer>> list() {
        List<Integer> l = new ArrayList<>();
        for(int i = 0; i < 10; i++) l.add(i);
        return rtJson(l);
    }
}

访问: http://localhost:8080/index 返回:

{
    code: 200,
    data: { },
    msg: "成功"
}

访问:http://localhost:8080/list 返回:

{
    code: 200,
    data: [
        0,
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9
    ],
    msg: "成功"
}

整个目录结构:

javaapp
├─pom.xml
├─src
|  ├─main
|  |  ├─java
|  |  |  ├─com
|  |  |  |  ├─jdz
|  |  |  |  |  ├─App.java
|  |  |  |  |  ├─controllers
|  |  |  |  |  |      ├─BaseController.java
|  |  |  |  |  |      └IndexController.java
|  |  |  |  |  ├─config
|  |  |  |  |  |   └MyFastJsonConfig.java
|  |  |  |  |  ├─beans
|  |  |  |  |  |   ├─ErrType.java
|  |  |  |  |  |   └RtData.java

后面我们所有的项目,都以这个为模板,在这个基础上进行开发迭代。

系列文章
【SpringBoot Web框架实战】01 使用 pom 方式创建 SpringBoot 第一个项目
【SpringBoot Web框架实战教程】02 SpringBoot 返回 JSON
【SpringBoot Web框架实战教程】03 SpingBoot 获取 http 请求参数


近期文章
# 车联网
【自动化运维】不要相信人,把所有的东西都交给机器去处理
从华为无线网络框架说Dispatch服务
百万级物联网框架设计
高并发服务器之泄峰
 

# 硬件
stm32驱动直流电机实现启动/加速/减速/倒车/停车等功能
stm32 定时器输出比较(OC)与PWM的理解和应用
stm32 定时器中断
STM32 外部中断的理解

  • 17
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiongxianhe

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值