我们写的 Spring Boot 这一系列文章,是以最终开发一个web api项目为目标,根据开发所需,逐步来学习和撰写的。比如:
- 第一篇 使用 pom 方式创建 SpringBoot 第一个项目,这篇介绍了如何以最简单的方式运行了一个 Spring Boot 项目;
- 第二篇 Spring Boot 返回 JSON,描述了如何返回 json 格式数据;
- 第三篇 Sping Boot 获取 http 请求参数,介绍了如何使用 Spring Boot 获取 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
后面我们所有的项目,都以这个为模板,在这个基础上进行开发迭代。