目录
[1.1 分析业务流程](#1.1 分析业务流程)
[1.2 接口统计](#1.2 接口统计)
[1.3 接口分析设计](#1.3 接口分析设计)
[1.3.1 接口分析和设计的一般方法](#1.3.1 接口分析和设计的一般方法)
[2.1 字段分析](#2.1 字段分析)
[2.2 ER图](#2.2 ER图)
[2.3 表结构](#2.3 表结构)
[2.4 创建分支](#2.4 创建分支)
[2.5 状态枚举](#2.5 状态枚举)

需要强调的一点是,开发中最重要的环节其实是前两步:
- 原型分析、接口设计
- 数据库设计
1.接口设计
1.1 分析业务流程
根据产片原型和页面说明,推测业务流转过程,画出流程图
1.2 接口统计
梳理一下在整个过程中开发人员可能要做哪些事情,这些事情将来就可能是我们要实现的服务端接口。梳理的方式就是查看原型图,分析哪里可能产生用户交互行为。
1.3 接口分析设计
那为什么要先设计接口呢?原因有两点:
- 第一:目前企业开发的模式往往是前后端分离,前后端并行开发。前端开发需要调用后端接口,后端需要开发接口返回数据给前端,要想并行开发,就必须有一套接口标准,前后端基于接口完成开发。
- 第二:设计接口的过程就是分析业务的过程,弄清楚了业务的细节,更有助于我们设计数据库结构,开发接口功能。
因此,我们将遵循企业开发的流程,先分析原型、设计接口,再设计数据库结构,最后再开发接口功能。
1.3.1 接口分析和设计的一般方法
企业开发中往往会通过一些工具来设计API接口,比如比较常见的一款API接口工具:https://yapi.pro/
我们先来看一下这个工具的接口设计页面,它分成三大部分:
- 基本设置
- 请求参数设置
- 返回数据设置
首先是基本设置:

在这里要填写的是某个接口的基本信息,例如接口名字、分类(或者叫分组)、状态等。但其中最重要的就是接口的路径。路径中需要填写的核心有两部分:
- 请求方式:也就是http请求的方式,本例中是GET
- 请求路径:也就是请求的资源路径,本例中是/users
知道了这些信息,前端就知道该向哪里发送请求了。
然后是当前接口的请求参数设置:

这里主要描述查询参数的基本信息,包括:
- 参数名称
- 参数是否必须
- 参数示例
- 参数描述
由于这里是查询用户集合,请求方式是GET,因此查询参数就是普通的QUERY参数,也就是路径后的?
拼接参数。如果是POST或者PUT请求,这里还可以传递更复杂的参数格式,比如FORM表单、JSON等
知道了这些,前端就知道发送请求时,要携带哪些参数了。
最后一部分就是返回数据设置:

这里就定义了返回的详细信息:
- 字段名称
- 字段类型
- 字段示例
知道了这些信息,前端就知道渲染时可以使用的字段了。
综上所述,接口设计的核心要素包括:
- 请求方式
- 请求路径
- 请求参数格式
- 返回值格式
知道了上述信息,前端就知道该向哪里发请求、请求要携带哪些参数、请求可以得到什么结果。而后端也能根据这些信息定义Controller接口、知道接口方式和路径、方法的参数、方法的返回值格式了。
但问题来了,上述要素我们该如何得知呢?
一般来说,可以按照下面的思路来设计:
- 请求方式 和请求路径:这一部分只要遵循Restful风格即可
- 请求参数 和返回值格式:结合页面原型和需求,与前端、后端、产品的同事共同协商决定。
这里比较复杂的就是参数和返回值,在分析的时候切忌自己臆想,不确定的地方一定要跟 产品经理 反复确认,最好邮件确认,避免以后扯皮。
然后与前端协商,或者跟调用你接口的后端同事协商。看页面渲染、其它服务需要哪些数据,而我们要查询这些数据需要哪些参数,最终确定接口的参数和返回值格式。
注意,上述过程不是一蹴而就的,很有可能会经过多次调整,这是非常正常的现象,核心思想就是一定要多沟通,多确认,不要自己任意妄为。
2.数据结构
基于之前的分析,我们已经知道了业务基本流程、用户的交互行为。而用户的这些行为必然产生数据,需要保存到数据库中。这些数据在保存时必须有设定好的结构,这样才能支撑我们完成各种接口功能。
2.1 字段分析
2.2 ER图
可以结合原型图中包含的信息来画一个ER图,以我的课表举例:

2.3 表结构
基于ER图,课表对应的数据库结构应该是这样的:
CREATE TABLE learning_lesson (
id bigint NOT NULL COMMENT '主键',
user_id bigint NOT NULL COMMENT '学员id',
course_id bigint NOT NULL COMMENT '课程id',
status tinyint DEFAULT '0' COMMENT '课程状态,0-未学习,1-学习中,2-已学完,3-已失效',
week_freq tinyint DEFAULT NULL COMMENT '每周学习频率,每周3天,每天2节,则频率为6',
plan_status tinyint NOT NULL DEFAULT '0' COMMENT '学习计划状态,0-没有计划,1-计划进行中',
learned_sections int NOT NULL DEFAULT '0' COMMENT '已学习小节数量',
latest_section_id bigint DEFAULT NULL COMMENT '最近一次学习的小节id',
latest_learn_time datetime DEFAULT NULL COMMENT '最近一次学习的时间',
create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
expire_time datetime NOT NULL COMMENT '过期时间',
update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (id),
UNIQUE KEY idx_user_id (user_id,course_id) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='学生课表';
2.4 创建分支
一般开发新功能都需要创建一个feature类型分支,不能在DEV分支直接开发,因此我们需要新建一个功能分支。我们在项目目录中打开terminal控制台,输入命令:
git checkout -b feature-lessons
2.5 状态枚举
在数据结构中,课表是有学习状态的,学习计划也有状态:

这些状态如果每次编码都手写很容易写错,因此一般都会定义出枚举:

@Getter
public enum LessonStatus implements BaseEnum {
NOT_BEGIN(0, "未学习"),
LEARNING(1, "学习中"),
FINISHED(2, "已学完"),
EXPIRED(3, "已过期"),
;
@JsonValue // 指定JSON序列化枚举时用的值
@EnumValue // 指定与数据库交互时要做类型转换的值
int value;
String desc;
LessonStatus(int value, String desc) {
this.value = value;
this.desc = desc;
}
@JsonCreator(mode = JsonCreator.Mode.DELEGATING) // 指定JSON反序列化时使用的函数
public static LessonStatus of(Integer value){
if (value == null) {
return null;
}
for (LessonStatus status : values()) {
if (status.equalsValue(value)) {
return status;
}
}
return null;
}
}
这样以来,我们就需要修改PO对象,用枚举类型替代原本的Integer
类型:

MybatisPlus
会在我们与数据库交互时实现自动的数据类型转换,无需我们操心。