不积跬步,无以至千里;不积小流,无以成江海。大家好,我是闲鹤,微信:xxh_1459,十多年开发、架构经验,先后在华为、迅雷服役过,也在高校从事教学3年;目前已创业了7年多,主要从事物联网/车联网相关领域和业务。喜欢交友、骑行、写毛笔字、弹吉他、折腾硬件和写代码。
导读
这是一系列关于 SpringBoot Web框架实战 的教程,从项目的创建,到一个完整的 web 框架(包括异常处理、拦截器、context 上下文等);从0开始,到一个可以直接运用在生产环境中的web框架,所有源码均开源。
正文
我们写的 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
后面我们所有的项目,都以这个为模板,在这个基础上进行开发迭代。
系列文章
【SpringBoot Web框架实战】01 使用 pom 方式创建 SpringBoot 第一个项目
【SpringBoot Web框架实战教程】02 SpringBoot 返回 JSON
【SpringBoot Web框架实战教程】03 SpingBoot 获取 http 请求参数
近期文章
# 车联网
【自动化运维】不要相信人,把所有的东西都交给机器去处理
从华为无线网络框架说Dispatch服务
百万级物联网框架设计
高并发服务器之泄峰
# 硬件
stm32驱动直流电机实现启动/加速/减速/倒车/停车等功能
stm32 定时器输出比较(OC)与PWM的理解和应用
stm32 定时器中断
STM32 外部中断的理解