【项目】餐饮管理系统1.0
[toc]
CMS项目设计说明书
演示视频:B站
一,需求分析
1.1 项目介绍
项目名:餐饮管理系统1.0/CMS(CateringManagementSystem)
项目特色:基于Java SE 和 MySQL的小型餐饮行业管理系统的控制台程序
作者:SWU——21信管5龙箫, 21信管4黄锦,21信管3李敏灿(leader)
分工:
龙箫:
- properties文件配置
- libs下druid,mysql-connector-java,commons-dbutils等资源jar收集和准备
- utils工具类的设计和编写
- DAO执行类的设计和编写
黄锦:
- 设计 MySQL 各张表
- domain类的设计和编写
- service各类的功能代码的完成
李敏灿:
- 设计项目架构方案
- 设计接口和父类以及各类属性和方法的制定
- 编写View界面类,并联合团队同学把程序跑起来
- 编写项目设计说明书
合作方式:Git配合GitHub的分布式版本控制开发
代码量:1200行
1.2 项目背景
该项目适用于个体户餐饮行业的日常客户商家管理,商家可以通过使用该系统,更加方便的进行贸易活动。
1.3 项目目的
巩固Java SE 和 MySQL 相关知识,提升小组人员对于复杂业务需求下的实践开发能力
二,总体设计
采用分层结构,整个项目主要用 Java SE 和 MySQL 写成。
2.1 功能介绍
系统登录:通过JDBC与MySQL数据库核实检验(做了防SQL注入处理)
酒店管理系统(二级菜单)
显示餐桌状态
预定餐桌
显示所有菜品
点餐
查看账单
结账
退出系统
2.2 程序架构图
2.3 项目分层
View层:界面层。负责调用Service层获取数据和行为进行显示
Service层:业务层。主要是各类业务衔接和操作
DAO层:具体的去执行Service层下达的指令,
domain层:主要存放Javabean和MySQL中表的对应关系
MySQL数据库:具体存放数据
utils类:常用工具类,提高工作效率
三,详细设计
3.1 体现原则
1、单一职责原则(Single Responsibility Principle)
2、依赖倒置原则(Dependence Inversion Principle)
3.2 体现模式
代理模式
各司其责模式
3.3 结构详细讲解
MySQL 数据库
需要不同的表就在目标数据库下建立不同的表
domain类
这个主要是在Java程序段形成Javabean和MySQL库中的表的类型对应。比如,你数据有个表是 student ,然后你读了一个 student 的数据到了程序来,需要载体去接受。这时候我们就可以直接 new 一个 domain 中对应的 Javabean 就可以了。
DAO层
这层全是实际操作数据的,实际干活的,他们从 Service 得到指令,然后去具体执行,去操作数据库。我们的原则表示,这里会有一个 BasicDAO 这个是所有 DAO 共有的操作,就放在这里面。然后我们每多了一个 domain 类 就建立一个 对应去操作这种对象的 DAO ,然后继承 BasicDAO ,之后再在本 DAO 中加上自己的特殊操作,如果有的话。
这里的 BasicDAO 有点讲究,它和下面那个JDBCUtilsByDruid 一样,都是包装好的,这个是把DML增删改用个 update就行了。但是对于查询,我们做了根据实际应用做了更加具体的分类:queryScalar查询单行单列的方法,即返回单值的方法;querySingle查询单行结果 的通用方法;queryMulti返回多个对象(即查询的结果是多行), 针对任意表。更加具体的实现我们在编码解释。
utils 类
这是一个工具类。里面有两个工具。
-
一个是 Utility
功能:处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入。看下图,具体都是干啥的,我们代码阶段讲解。
-
另一个是封装的 JDBCUtils
连接池用的阿里的 Druid (德鲁伊)。因为用Java操作MySQL获取连接很麻烦,所以就整个这个。它就一个getConnection 返回一个连接。还有个 close 这个是关闭资源用的,包括连接,statement,结果集等/具体的我们编码阶段讲。
Service层
这个也是根据实际业务需求来写,比如有那个DAO我们就写个对应专门操作他的Service,专事专办。当然这个是看具体任务,一个Service可以控制两个DAO也是正常。
View层
这个就是表层次的页面了,这个里面我们有一下几个方法,分别行驶不同的功能,比如listDiningTable是显示目前店内的餐桌适用情况;orderDiningTable是预定餐桌;listMune是列举菜单等等,具体的我们在编码给大家讲解。
四,编码
4.1 项目构成
1.包名
如下,总包为team.swu.lmc.HMS
符合规范:全部小写,按照team.学校.作者.项目名.模块名
格式命名
意为:该项目为团队项目,是 SWU
;学校项目队长为 lmc
; 项目名为 HMS
2. 包含
该项目由dao
;domain
,service
,utils
,view
五个包和一个start启动文件组成
start文件:是程序运行入口
view包:里面只有一个HMSView
是项目的界面
service包:全是相应的项目服务,是具体业务逻辑实现的地方。其中有四个文件
1. BillService:账单服务
1. DiningTableService:预定桌子服务
1. EmployeeService:登录人员管理服务
1. MenuService:菜单服务
dao包:主要是执行层具体干活的类。包含六个文件:
- BasicDAO:基本DAO,其他所有DAO的父类,包含大家的共用方法
- BillDAO:专门操作Bill账单的DAO
- DiningTableDAO:专门预定桌子的DAO
- EmployeeDAO:专门执行有关雇员操作的DAO
- MenuDAO:专门执行菜单有关的操作DAO
- MultiTableDAO:这个是在Bill表的基础上联合多表查询的专门DAO
domain包:和 MySQL 数据库中的表对应的 Javabean 类,具体有五个:
- Bill:账单
- DiningTable:预定餐桌
- Employee:雇员
- Menu:菜单
- MultiTableBean:联合多张表查询Bill数据的Javabean
utils包:该项目需要的工具包,主要就两个工具类:
- Utility类:处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入
- JDBCUtilsByDruid:一个封装的数据库工具,里面数据连接池用的阿里的德鲁伊。
4.2 每个代码块详细讲解
4.2.1 MySQL数据库
1.结构
2.解释
bill:账单表。
id是第几单,billID是订单号(做了防止重复的设计),menuId是菜品号,nums是点的菜品数目,diningTableId是几号桌子的,billDate是那个时间下单的,state是订单状态,如果支付了会有详细支付方式,如果没有买单就是未支付
diningTable:餐桌单。
id是桌号;state是餐桌状态,已预约就是预约好了但是还没有用餐;正在用餐就是已经上菜,在吃;空就是空闲的,orderName是定桌人姓名,orderTel是定餐人电话
employee:雇员表
empId是工号,pwd是密码(这里使用了MD5加密);name是雇员姓名;job是他的职位。
menu:菜单表
id是菜品号,name是菜品名,type是菜品类别,price是菜品价格
3.history代码
1 | -- 创建HMS数据库 |
4.2.2 utils
1. Utility
处理各种情况的用户输入,并且能够按照程序员的需求,得到用户的控制台输入。
-
构成结构
开头一个静态私有的Scanner
readKeyBoard私有静态方法
其他读取公开静态方法
-
readKeyBoard
-
readConfirmSelection
-
readString
-
readInt
-
readChar
-
readMenuSelection
2. JDBCUtilsByDruid
基于druid数据库连接池的工具类
为什么?
因为 Druid 集齐了 C3P0和其他数据库连接池的所有有点,更快更稳健,更加适配。
-
构成结构
一个私有静态的 DataSource+static代码块初始化+getConnection获取连接+close关闭资源
-
static代码块
主要用途就是完成那个 DataSource 的初始化。
相关信息是 src 下面的 druid.properties 配置文件 load 过来的,然后用 Druid数据池拿一个数据源给刚才的 DataSource 完成初始化。有问题就被try_catch 了。
-
getConnection 获取连接
直接用从 Druid 数据源中拿一个出来返回连接
-
close 回收资源
如果需要关闭就对应位置传入对象,没有就 null
里面先会判空然后再关闭
注意这里的关闭是把连接放回 Druid 数据库连接池
-
Druid 的配置文件
4.2.3 domain
与 MySQL 对应的 Javabean ,
构成:
-
MySQL 表中的对应元素(全部私有化),
-
然后构造器有有参和无参两种,
-
然后就是所有元素的getter&setter方法
-
还有一个便于打印该类元素的 toString
这里需要注意的是:
- 属性名最好和MySQL表中的列名保持一致
- 而且无参构造器和setter&getter方法必须要
- 否则会因为反射出现Bugs
4.2.4 DAO
这个是针对每个表的实际执行人。
构成
- domain中对应类的 XXDAO
- BasicDAO
- XXDAO都继承了BasicDAO
BasicDAO实现:
结构
一个内部私有new的驱动+一个增删改方法+3个数据库查询方法
update
SQL语句中的增删改DML
首先利用 JDBCUtilsByDruid 获取连接,然后用 QueryRunner 的update 传入相关参数去操作数据库。如果有异常捕捉后转换为运行异常并抛出。最后还是用 JDBCUtilsByDruid 的 close关闭相应的资源。
query类
这是用来操作数据库,查询信息的,根据用途分为查多条信息,查一条信息,一条信息中的一个数据三种
这个的原理和上面的 update 过程是相似的,唯一的区别是 用的是 query。区别三种查询类型的是第二个参数是(下图红框Bean),Bean的类型不同,返回的数据包装成不同的 Javabean。
4.2.5 service
这个是项目的主题,也是重头。主要是各个板块的服务逻辑书写
1. BillService
结构:
-
属性:
BillDAO;multiTableDAO;(给这些DAO下指令,去执行对数据库的操作)
menuService;diningTableService;(需要借助这两个类中)
-
方法:
orderMenu:点餐
list,list2:返回所有菜单(后面那个是多表查询)
hasPayBillByDiningTableId:查看某个餐桌是否有未结算的菜单
根据餐桌号返回符合条件的 Bill 对象,非空即为有未记账的账单
payBill:结账行为
首先在 Bill 表设置账单state,然后diningTable表中把桌子状态还原
2.DiningTableService
结构:
-
一个 diningTableDAO 私有对象
-
五个订餐相关方法
-
list:返回所有餐桌信息
-
getDiningTableById:根据 id ,查询对应的餐桌DiningTable 对象
如果返回null就是表示这个餐桌不存在 -
orderDiningTable:如果餐桌可以预定,调用方法,对其状态进行更新(包括预定人的姓名和电话)
-
updateDiningTableState:更新餐桌状态
-
updateDiningTableToFree:设置指定餐桌为空闲可用状态
3.EmployeeService
一个执行命令的 EmployeeDAO
一个按empId 和pwd 返回 Employee 对象的方法
唯一需要注意的就是下图标红的,需要用MD5加密否则匹配不上。
4.MenuService
一个执行命令的私有 MenuDAO
list:返回所有的菜品,返回给界面使用
getMenuById:根据菜品 Id 获取 Menu 对象
4.2.6 View
元素
loop:控制是否退出主页面
key:接受用户在主菜单的选择的
employeeService,diningTableService,menuService,billService:在 view 界面层中调用这些服务层
方法
listDiningTable
显示所有餐桌状态
核心就是:diningTableService.list()
orderDiningTable
完成定座
开始的时候判断两个需要推出的情况:输入 -1 和确定时输入 N
这两个没问题接着下面,先排除没这个桌子,和桌子在空的不可用情况,然后预定改变桌子状态在 餐桌表。
核心函数:diningTableService.getDiningTableById(orderId);diningTableService.orderDiningTable(orderId, orderName, orderTel)
listMune
显示所有菜品
核心就是:上图红框 menuService.list()
orderMenu
点餐
首先是确定点餐的三次没有输入 -1 退出
这些都 ok 的话,就要确认餐桌号存在,顾客点的菜品存在,之后才点菜。
主要就是下图红框的三个函数:
diningTableService.getDiningTableById(orderDiningTableId);
menuService.getMenuById(orderMenuId);
billService.orderMenu(orderMenuId, orderNums, orderDiningTableId)
listBill
显示账单信息
注释掉的是旧版本的,现在用了 MySQL 多表查询
payBill
完成结账
首先排除 -1 退出情况
再排除结账餐桌不存在和指定餐桌没有需要结账账单的两种情况
如果顾客再选择结账方式时候回车也是退出,最后确认输入 N 也是退出,或者支付账单出错也会取消,只有以上情况都排除才会顺利结账。
核心:就是排除各种需要终止结账的情况和下图红框方法
mainMenu
主菜单,用来显示的主页面
登录界面,衔接下一步选择是否登录
登录账号密码输入,然后会去数据库核实,都没有出错才会登录系统。数据库验证考虑到 SQL 注入,所以做了相关处理
核心:
- 就是第一个红框的数据库验证函数
- 各种拒绝登录的业务逻辑实现
系统二级选择菜单,选具体操作。对操作的处理在那个红框中
通过 switch 输入什么就执行什么业务逻辑,这里的方法是我们同类下面上面讲解的那些个静态方法
核心:红框函数
4.3 运行分析
登录
输入1:让你输入账号密码,正确了就会显示登录成功[XX],XX是登录者名字,然后显示系统的二级菜单,让你选择下一步操作。
输入1,但是账号密码没有全对,会提醒登录失败,然后让你重新选择
输入2:退出系统
输入1,2之外的数字:提示请正确输入指令
能登陆的都是 MySQL 表中的员工,密码不可见,因为用了 MD5 加密
1 查看餐桌情况
2 预定餐桌
顺利预定
顺利预定后查看,确实预定了
预定无法预定的餐桌
预定中途退出
3.显示所有菜品
4.点餐
顺利点餐
不顺利点餐
没餐桌
菜品不存在
5 查看账单
6 结账
顺利结账
不顺利结账
该餐桌没有账单
没有该餐桌
9.退出系统
4.4 遇到 Bugs
1.Druid配置文件错误
问题记录
测试两个工具类时,爆出 druid.properties 配置文件错误。
查看
原来是拷文件的时候没有改配置文件中的 url
中的数据库名
解决
新建一个 HMS 数据库,然后 druid.properties 中的目标位置girl
改为HMS
再次测试,ok
2.Jniut测试一直卡着跑不出来
情况记录
写完登录页面后用Jniut
进行测试,Run 之后却一直卡在运行测试给你转圈。程序也只跑了一些。
原因
用 Jnuit 做单元测试的时候是不允许控制台输入的,第30行有句向控制台读入,Jniut
在这里卡住了。
解决办法
帮助 -> 编辑自定义VM选项
在末尾加上一行:-Deditable.java.test.console=true
然后重启 IDEA,问题解决
3.domain是干什么的?
一般来说在数据库建了一个表后都会在旁建立一个domain类,然后里面写对应的 Javabean。
这个的意思就是,数据库中的那个表所要表达的对象形式在 Java 程序中的体现。比如你 MySQL 中有个学生表,有很多元素。那你读取在 Java 端怎么接受?必须有一个对应的对象类去表示它。这就是 domain。
4.在做显示所有菜品时,查出来全是null
情况描述
这里我们是用 用阿里Druid做的一个BasicDAO来批量查询,把数据一丢进去,以为会出来结果,结果全是null
出问题的地方:
问题所在
查询数据的那张菜单表的domain
对应Javabean类
没有getter&setter
加上getter&setter
原因
联系Java反射不难猜出这个BasicDAO
底层从数据库返回数据再注入到javabean
中,利用的反射的getMethod,getDeclaredMethod
等取得各字段的setter,getter
方法.没有setter,getter
方法就无法给javabean
注入属性,他们输出到控制台就都是初始值null
。验证方法,在开头给name
赋初始值大哥
,他就会只有第二个名字都是:大哥,然后其他的都是null
.
结论:建立domain类以及表示对象类,无参构造器,setter&getter都给默认带上,不然很多框架方法底层反射实现的东西都会报错或者异常。
五,测试
我们项目用的测试
单元测试框架junit
简介:
JUnit 是一个 Java 编程语言的单元测试框架。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。
优点:
- 可以书写一系列的测试方法,对项目所有的接口或者方法进行单元测试。
- 启动后,自动化测试,并判断执行结果, 不需要人为的干预。
- 只需要查看最后结果,就知道整个项目的方法接口是否通畅。
- 每个单元测试用例相对独立,由Junit 启动,自动调用。不需要添加额外的调用语句。
- 添加,删除,屏蔽测试方法,不影响其他的测试方法。 开源框架都对JUnit 有相应的支持。
策略:写一个功能就在 MainMenu 上加一个 Test 跑一下,形成单元性测试
六,软件打包
开发背景
开发IDE:IDEAIntelliJ IDEA 2020.2 (Ultimate Edition)
JDK:11.0.14 LTS
MySQL: Ver 14.14 Distrib 5.7.19, for Win64 (x86_64)
MySQL页面APP:SQLyog
访问方式
项目jar包:蓝奏云
密码:3vca
libs中的jar包:蓝奏云
密码:g0as
GitHub:仓库地址
七,学年设计总结报告
通过本次学年设计实践,我们小组成员都收获颇丰。我们学会了:
- Java SE 相关知识在项目中的具体实践;
- Java 通过 JDBC 操作 MySQL 的具体做法;
- 利用 Git 和 GitHub 进行多人团队协作版本控制开发;
- 自己写常用的 utils 工具类,可以几大的提升我们的开发效率;
- 学会了项目开发的模块化思想和 DAO分层理念,用界面层,服务层,DAO层,domain层,数据层,工具层协作开发,各司其责,条理清晰,结构严谨;
- 我们学会了 JDBC 进阶操作,怎么制作 JDBCUtils,利用 Apach——utils和阿里的Druid连接池做成一个DAO模式,极大的提高了,Java 操作数据库的效率,也极大地方便了开发;
- 在项目测试方面我们采用了 junit,而且我们通过试错Bug对他的适用和了解进一步加深了;
- 我们还通过 Bug 进一步深入了解了,反射在 JDBC 底部,和 Druid 连接池底池的作用和重要性