后端代码生成工具SDP系列五(10分钟写一个学生课程管理系统)
10分钟写一个学生课程管理系统
创建数据库(建议使用mysql8数据库)
标题要大,其实十分钟可能都没法将本文仔细看完。10分钟其实指的是实际操作,至于真正地生成所有的代码需要做的可能1分钟都不到。
这个demo仅有几个数据表,其中3个表:学生、课程和选课关系表,参考自《数据库系统概论》第五版 +学习笔记总目录中的“chp3-1.ppt”第30、31、32页。
另外,表、字段都以下划线进行了分割。原因是个人习惯,另外也是为了统一管理,因为前后端通讯时会统一使用下划线规则(ajax规则),而后端java内部会使用驼峰规则,驼峰和ajax规则使用下划线进行区分会更简单易记。
CREATE TABLE sc_dept
( d_no VARCHAR(9) primary key comment '班级编号',
d_name VARCHAR(20) UNIQUE comment '班级名称',
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '更新时间',
updated_by VARCHAR(45) comment '更新人'
) comment '班级';
CREATE TABLE sc_student
( s_no VARCHAR(9) primary key comment '学号',
s_name VARCHAR(20) UNIQUE comment '学生姓名',
s_password VARCHAR(45) comment '密码',
s_sex VARCHAR(2) comment '性别',
s_birthday DATETIME comment '生日',
d_no VARCHAR(9) comment '班级编号',
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '更新时间',
updated_by VARCHAR(45) comment '更新人',
FOREIGN KEY (d_no) REFERENCES sc_dept(d_no)
) comment '学生';
CREATE TABLE sc_teacher
( t_no VARCHAR(9) primary key comment '教师编号',
t_name VARCHAR(20) UNIQUE comment '教师姓名',
t_password VARCHAR(45) comment '密码',
t_sex VARCHAR(2) comment '性别',
t_birthday DATETIME comment '生日',
t_is_admin SMALLINT comment '是否为管理员',
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '更新时间',
updated_by VARCHAR(45) comment '更新人'
) comment '教师';
CREATE TABLE sc_course
( c_no VARCHAR(9) PRIMARY KEY comment '课程编号',
c_name VARCHAR(20) comment '课程名称',
c_pno VARCHAR(9) comment '先修课程',
c_credit SMALLINT comment '学分',
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '更新时间',
updated_by VARCHAR(45) comment '更新人',
FOREIGN KEY (c_pno) REFERENCES sc_course(c_no)
) comment '课程';
CREATE TABLE sc
( s_no VARCHAR(9) comment '学号',
c_no VARCHAR(9) comment '课程编号',
approve_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '批准时间',
approve_t_no VARCHAR(9) comment '批准选课的教师编号',
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '更新时间',
updated_by VARCHAR(45) comment '更新人',
PRIMARY KEY (s_no, c_no),
FOREIGN KEY (s_no) REFERENCES sc_student(s_no),
FOREIGN KEY (approve_t_no) REFERENCES sc_teacher(t_no),
FOREIGN KEY (c_no) REFERENCES sc_course(c_no)
) comment '选课';
CREATE TABLE tc
( t_no VARCHAR(9) comment '教师编号',
c_no VARCHAR(4) comment '课程编号',
updated_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '更新时间',
updated_by VARCHAR(45) comment '更新人',
PRIMARY KEY (t_no, c_no),
FOREIGN KEY (t_no) REFERENCES sc_teacher(t_no),
FOREIGN KEY (c_no) REFERENCES sc_course(c_no)
) comment '执课';
数据库ER模型及业务简单介绍
系统有3个角色:学生、教师、管理员(也是教师,但是属性t_is_admin为1)。
1)学生角色:学生可以自主选择课程,并存入sc表,即学生可以对sc表进行insert操作。
2)教师角色:教师负责对sc表进行审批操作,审批通过后,sc表的approve_time和approve_t_no会设置为对应的审批时间和审批教师。只有tc表(教师-课程关系表)中有关联记录的教师才能对相应的sc表记录进行审核。
3)管理员(t_is_admin属性为1的老师):管理员有所有权限,包括新建班级、学生、教师,以及维护tc表(即教师-课程关系表)、申请课程、审批课程。
步骤一:新建数据库
在mysql8中先创建好database,例如sc,然后将上述sql语句在数据库工具中执行。
步骤二:下载SDP工具和模板文件
本文使用的版本是1.5,从https://pan.baidu.com/s/1J0PjXcbxUVmQRZzRUAs1kg?pwd=7hn4下载打包好的SDP工具,或到github下载源代码编译运行。
本文中使用到的SDP模板文件从这里下载:https://pan.baidu.com/s/10bJJYK_gxN2o5qbverVUtQ?pwd=x9as
步骤三:运行SDP工具
解压下载好的文件,执行其中的startup.bat,会启动一个命令窗口,内容如下图所示:
步骤四:启动前端管理工具并导入模板
在浏览器中输入http://localhost:9999,待页面显示后,点击“导入”按钮,如下图所示:
在“文件”项里,选择“点击上传”,找到SDP下载文件中的sdp_demo_sc.txt文件。然后点击“开始导入”。如下图所示:
步骤五:修改数据库配置信息
为了安全起见,即便是在同一台机器、同一个环境下,SDP工具在导出和导入时,也不处理已经配置的数据库密码。所以导入后,需要手工修改数据库密码。导入后的页面信息如下,选择“demo_sc”工程,然后点击“修改”按钮,页面如下:
在“修改”页面中,输入正确的信息,然后可以点击“测试连接”按钮,看到“成功”提示,即表示数据库配置正确,如下图所示:
步骤六.1:创建源代码目录,并生成所有的前、后端代码
切换到sdp3_project页面,并设置源代码主目录,如下图所示:
SDP工具为了安全起见,要求“路径”必须存在,才可以在对应的目录中生成文件。我们可以点击“设置(root)目录”按钮,设置代码的主目录。
目录建立好以后,需要选中一条数据,或在“工作区”查询条件中选择"demo_sc",然后点击“执行”按钮。即可自动生成所有的文件。执行成功的页面如下图所示:
步骤六.2 为什么project页面的“表”有区别
SDP工程生成的文件数量是以project的记录为分组的条件,每条project中的“表”可以包含0到任意多个表,多个表以英文逗号分隔。每个表都会和template中的记录进行关联,例如project中server_api类型在template中对应9个模板文件,server_controller在template中对应3个模板文件。如果我们在server_api和server_controller中都设置了6个表,那么最后我们通过“执行”,就可以自动得到9乘6+3乘6个源代码文件。当然,可能会多于这个数量,因为SDP工具提供了自动处理复杂select语句的功能,允许额外针对定制的select生成对应的api request文件、api response文件、dao层实体文件、dao层Mybatis example文件等。
project中两个特殊的记录:server_static和web_static仅对应了一个sc表,这个sc表仅仅用于占位,其实这两个project对应的template与表无任何关系,均为一些基础代码、配置文件,例如pom.xml等。如果不配置,那么就不会生成这些基础表,如果配置了多个,那么其实也只是重复覆盖。
步骤六.3 允许生成的文件和表名不一样
在融合多个系统,或改造原有系统时,我们可能已经有了很多表,但是这些表在新系统中已经有对应的表、对象,那么我们就可以通过在sdp3_project的“表”中使用:a as b的方式,将数据库中的a表生成的文件替换为b。
步骤七.1 查看生成的结果
“执行”后,可以到对应的目录中查看SDP工具根据“sdp_demo_sc.txt”这个模板生成的所有代码。后端代码是标准的spring boot工程,基础的架构是分成3层:controller、service、dao。前端代码使用了vue3技术。
步骤七.2 SDP如何巧妙地实现了定制化业务代码和自动生成代码的融合
在sdp4_template中,每个模板文件都有一个属性:“不覆盖生成”,这个属性如果为1,那么就表示文件仅生成一次,例如所有的custom controller和custom server,以及所有的static_server、static_web文件,这些文件一旦生成后,开发者可以继续修改,SDP工具不会再对这些文件进行覆盖。
SDP工具在后端架构中增加了两层:custom controller和custom service层,他们通过继承(上有老、下有小)的方式,将定制化业务拆分到了独立的文件中。
demo生成的前端代码也采用了类似的技术,除了生成基本的页面外,对应地提供了简易的定制化方案。
需要说明的是,后端的5层已经非常成熟,基本可以应对所有的spring boot开发场景。前端由于其开发特性和大量的交互、展示需求,所以基本无法实现简单的分层开发方法。本demo中提供的更偏向于类似简单的企业管理系统、后台管理系统的前端框架。
另外,可以通过demo提供的前端框架,快速搭建可视化的接口测试页面,效果和效率比postman要好很多。
步骤八 打开后端工程,并执行
打开Idea(社区版即可):Idea下载地址。
步骤如下:
8.1打开Idea,点击“Open or Import”:
打开工程后,如果是第一次打开后台工程,需要耐心等待idea下载对应的依赖文件,可以点开右下角的"processes running…"查看下载的进度。
如果Idea没有配置过lombok插件,那么需要安装lombok插件,具体方法自行搜索。。。
8.2 修改数据库配置
为了安全,demo生成的server\src\main\resources\application.yml文件中没有数据库密码,所以需要手工修改数据库密码,页面如下:
8.3 启动后端服务
修改好数据库密码后,找到server\src\main\java\org.example\MyApplication.java,选择这个文件,点击鼠标右键,选择“Debug ‘MyApplication.main()’”,如下图所示:
运行后,Idea会自动打开“Debug”面板,可以看到控制台输出“Started MyApplication。。。”,就代表后端已经成功启动。如下图所示:
步骤九 测试后端服务
测试之前,我们先要了解后端提供了哪些接口。回顾步骤6,sdp3_project中的server_controller对应的每个表,都会生成对应的若干标准接口,这些接口都在对应的server\src\main\java\org\example\controller目录中,例如sc_dept表对应的ScDeptController.java内容如下:
package org.example.controller;
import org.example.controller.custom.*;
import org.example.dto.request.*;
import org.example.dto.response.*;
import java.util.List;
import org.springframework.web.bind.annotation.*;
/**
* @ClassName: ScDeptController
* @Description:
* @Author: SDP
* @Date: 2022-01-08
* @Version: 1.0
* Table: sc_dept
* Comment:
* 班级
*/
@RestController
@RequestMapping(value = "/sc_dept")
public class ScDeptController extends ScDeptCustomController {
@PostMapping("/add")
public int addScDept(@RequestBody ScDeptAddRequest request) throws Exception {
super.fixRequest("sc_dept", "add", request);
return super.addScDept(request);
}
@PostMapping("/update")
public int updateScDept(@RequestBody ScDeptUpdateRequest request) throws Exception {
super.fixRequest("sc_dept", "update", request);
return super.updateScDept(request);
}
@PostMapping("/delete")
public int deleteScDept(@RequestBody ScDeptDeleteRequest request) throws Exception {
super.fixRequest("sc_dept", "delete", request);
return super.deleteScDept(request);
}
@PostMapping("/query")
public ScDeptQueryResponse queryScDept(@RequestBody ScDeptQueryRequest request) throws Exception {
super.fixRequest("sc_dept", "query", request);
return super.queryScDept(request);
}
@PostMapping("/list")
public List<ScDeptQueryResponse> listScDept(@RequestBody ScDeptQueryRequest request) throws Exception {
super.fixRequest("sc_dept", "list", request);
return super.listScDept(request);
}
@PostMapping("/count")
public int countScDept(@RequestBody ScDeptQueryRequest request) throws Exception {
super.fixRequest("sc_dept", "count", request);
return super.countScDept(request);
}
}
每个表都包含和3个基础的DML接口:add、update、delete,一个query接口(以primary key为条件的唯一性查询),一个count接口(计数),一个list接口(单表查询)。
我们可以使用postman来测试sc_dept的这些接口。也可以通过demo提供的前端,来更直观的测试这些接口。
步骤十 启动前端
首先,我们需要先安装好node开发环境:下载NodeJS。
然后双击生成的前端代码(web目录)下的install.bat。或手动启动命令窗口,切换到生成的d:\git\sc\web目录,执行npm install。
准备工作结束后,我们可以双击web目录下的startup.bat。或在命令窗口中输入npm run dev。等待前端启动完成,由于demo使用了vue3的vite作为开发、打包工具,所以启动、打包速度飞快。感谢“vue-manage-system”工程:vue-manage-system地址,本demo中的基础框架使用了这个工程的代码构建。启动成功的页面如下图所示:
步骤十一 开始使用
启动浏览器,输入http://localhost:3000,即可看到页面了。所有的表、每个表对应的增删改查都可以正常测试。图示:
后续:定制化页面、定制化接口
这个demo目前仅展示了SDP工具的基础功能:生成标准的代码、标准的增删改查接口。下一次,我们将继续这个demo,讲述如何定制前端页面、定制后端复杂接口。