004 Spring Boot 规范统一输出 json

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

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

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

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

创建返回的数据结构

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

字段 类型 含义
code Int 返回码
msg String 文本描述
data Object/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

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

源码: https://github.com/xiongxianhe/springboot/tree/master/004%20%E8%A7%84%E8%8C%83%E7%BB%9F%E4%B8%80%E8%BE%93%E5%87%BA%20json

发表评论