Springboot酒店会员点餐系统
摘 要
进入21世纪以来,计算机有了迅速的发展。计算机应用、信息技术全面渗透到了人类社会的各个方面,信息化已成为世界经济和社会发展的大趋势。―企业的管理也从人工操作变得更加自动化、智能化和高效化。如果复杂的工作光靠人工来完成,势必浪费很多的时间,而且又很容易出差错。本文主要通过对酒店会员点餐系统的功能性需求分析,对系统的安全性和可扩展性进行了非功能性需求分析。在详细的需求分析的基础上,根据系统的功能设计确定了数据库结构,实现完整的代码编写。酒店会员点餐系统完成了主要模块的页面设计和功能实现。本文展示了首页页面的实现效果图,并通过代码和页面介绍了用户注册、酒店资讯、酒店房间、酒店菜品、酒店酒水、酒店餐具管理功能的实现过程。
关键词:酒店会员点餐;Springboot框架;数据库
Springboot hotel member ordering system
Abstract
Since entering the 21st century, computers have developed rapidly. Computer application and information technology have fully penetrated into all aspects of human society. Informatization has become the general trend of world economic and social development The management of enterprises has also changed from manual operation to more automation, intelligence and efficiency. If complex work is completed only by manual work, it is bound to waste a lot of time, and it is easy to make mistakes. This paper mainly analyzes the functional requirements of the hotel member ordering system, and analyzes the non functional requirements of the security and scalability of the system. Based on the detailed demand analysis, the database structure is determined according to the functional design of the system to realize the complete coding. The hotel member ordering system has completed the page design and function realization of the main modules. This paper shows the implementation effect of the home page, and introduces the implementation process of user registration, hotel information, hotel rooms, hotel dishes, hotel drinks and hotel tableware management functions through codes and pages.
Key words: Hotel member ordering; Springboot framework; database
目 录
一、 绪论 5
(一) 研究背景与意义 5
(二) 国内外研究现状 5
二、 开发工具及相关技术介绍 6
(一) J2EE技术 3
(二)MVVM模式 3
(三) B/S结构 3
(四) Springboot框架 3
(五) Mysql数据库 4
(六) B/S体系工作原理 4
三、 系统分析 7
(一) 可行性分析 7
1. 经济可行性 7
2. 技术可行性 7
3. 操作可行性 7
(二) 功能性需求分析 7
(三) 非功能性需求分析 11
(四) 业务流程分析 11
四、 系统设计 12
(一) 功能模块设计 12
(二) 数据库设计 14
1. 概念模型设计 14
2. 数据库表设计 15
五、 系统实现 17
(一) 用户登录的实现 18
(二) 系统前台主要功能实现 18
(三) 系统后台主要功能实现 21
六、 系统测试 24
(一) 系统可靠性测试 24
(二) 系统功能性测试 24
(三) 系统合格性测试 25
(四) 测试结果 25
七、 总结与展望 26
参考文献 27
致谢 27
人们生活水平日渐提高,外出就餐的次数也逐渐增多,传统服务员拿着纸质菜单协助点餐的模式慢慢露出弊端,这不仅会造成餐厅拥堵,还会影响消费者的就餐体验。在此种情况下,将计算机技术与餐饮管理过程相结合,提高就餐过程的效率和用户体验是大势所趋,也是我国信息化建设必不可少的一项任务。2020年的政府工作报告中提到,要全面落实“互联网+”进程,打造数字经济优势。餐饮行业作为传统行业的重要组成部分,数字化进程相对其他新兴行业来说较为缓慢。在席卷全球的新冠疫情下,率先落实“互联网+”与数字化布局的餐饮企业呈现出了更好的抵御风险能力和快速市场恢复能力。“互联网+”的融入为传统行业的发展带来了新的契机和活力。
餐饮业的发展,由最初满足人们外出工作时的饱腹需求,现已形成了丰富的模式,并逐步衍生出互联网+餐饮模式,以此为人们提供更完善、更便捷、更具个性化的饮食体验。随着餐饮管理软件的出现,互联网+餐饮模式不仅吸引更多客户为餐饮企业创收,还能优化餐厅管理,实现餐饮企业运营体系化升级。现阶段的点餐系统主要包括两种模式,一种是外卖点餐软件,消费者线上点餐、线下配送;另一种是店内点餐系统,消费者在店内点餐。基于自助点餐机器,消费者无需询问服务人员,可直接在点餐机器上浏览所有的餐饮图片、菜品特色介绍等,同时可根据客户喜好推荐相关菜品,即节省了客户时间也可简化餐厅的人员配置。
虽然我国餐饮行业规模越来越大,现在大部分餐饮行业商家并没有花大量时间和精力打造自己的点餐系统,更多的是使用第三方平台实现最基本的点餐与支付。这并不能直接获得到客户的消费数据,在大数据时代,这些数据都是很珍贵的。其次,商家和客户的互动性不强,不能及时有效地收集客户的用餐反馈如对菜品的评价,商家可根据这些评价信息对菜品做出适当的调整。菜品都是单一价格,没有一个好的会员体系来促进客户消费,客户粘度不高。
因此,在已有点餐系统的基础上,从酒店商家的实际需求出发,开发一套融合会员机制的酒店点餐系统,对会员提供菜品优惠价、账户充值优惠等折扣,本系统分为客户点餐端和商家管理端两大模块,致力于为客户提供优质用餐体验,提高客户粘度,提升酒店经营业绩。
国外电子点餐系统起步较早,80年代以来,餐厅开始建立自己的订单管理系统,使用电子技术完成订购结算业务。80年代末开始,移动PAD餐厅无线点餐系统在世界各地出现,改变了传统手写菜单、传递菜单的模式,促进餐厅整体效率的提升,降低服务员的工作强度。此后互联网、智能手机的全面普及推动着餐厅信息化建设迈进全新的时代。2001年,美国一家餐厅首次使用了点餐宝,消费者在进行点餐时,服务员负责将点餐信息录入到该系统中,厨房能实时收到点餐数据,大大提高了点餐效率。德国有企业于2007年推出全球首个无人餐厅,餐厅内所有的服务都无人参与,顾客全程通过店中的设备完成包括搜索菜品、点餐、买单等服务,开创了就餐新局面。此后,日本的一家餐厅在前人工作的基础上进一步结合移动互联网技术,将点餐系统部署于智能终端上,顾客可以在餐厅APP上预约、排号及点菜退菜,这种就餐模式极大地节约了顾客的时间,避免了餐厅拥堵,更加符合现代人的生活节奏。
黄成谋,施键兰(2019)主要设计了一个在手机上使用的自助点餐App系统。该系统的数据库基于SQL-Server。该文主要给出了系统设计的各个功能模块和结构框架,阐述了实现了相关功能的过程,设计思路和E-R图。该项目达到了预期的效果,实现外卖点餐的整个流程。该项目的主要价值是为了节省用户与商家的时间,提高了点餐效率。
霍涛,山宇韬,王俊豪(2019)介绍了一种基于J2EE的网络订餐系统的功能设计及实现技术,系统功能主要包括餐品管理、订餐、户订单处理、系统管理等,能够实现用户与商家之间的网络点餐交易。该系统界面简单直观,易于操作和使用,交互性强,适合在中小型餐饮企业中推广使用,有利于提高餐饮业者的企业竞争力。
赵泽忠,程江珂(2019)针对餐饮业的传统消费模式,点餐,上菜,买单等均需要人工进行操作,管理的人力、物力以及资源的浪费等问题,该文设计与开发了基于移动端的智能点餐系统,主要进行了菜品展示,菜品购买以及账单结算等主要功能模块设计;再通过对系统进行具体的代码实现;最后经过黑盒测试验证了系统的合理性、可行性以及稳定性。
陈南平(2020)针对餐饮店的客户点菜流程,设计了一个移动Web点餐系统。该系统采用SOA面向服务的分布式架构,客户端使用H5和WebAPP技术,使进店客户可通过手机扫描餐厅的二维码,进而在手机上浏览菜品并智能点餐。同时,系统提供线上订餐服务,用户可以利用手机在线下订餐。客户端利用WebSocket技术将点菜数据实时共享到同桌用户的手机上,实现了同桌多人同时点餐。本系统不仅改善了客户点餐时的用户体验,也使餐饮服务更加高效和经济。
古入次仁,陈浩,索南尖措(2020)针对校园里传统的点餐、上菜、预定等需要通过人工来完成的工作带来餐馆人员的浪费和用户多而饭菜供应速度慢,使用户需要排长队的问题文章设计开发了基于Web端的智能点餐系统,实现了菜品的查看和点餐、用户的注册、登录、信息录入等多个模块,搭建系统环境和介绍工具等来设计校园智能点餐系统。
涂敦兰,王莎(2020)针对传统就餐点餐流程出现的问题,进行需求分析,对点餐流程和功能模块进行分析,设计一款以单片机为主控器的智能点餐系统。该系统结合红外线传感器、嵌入式芯片、无线传感器、语音模块等设备,把点餐数据传输到服务器。智能餐厅由手机终端APP与智能管理终端机两部分组成,拥有实时的快餐制作的流程、提前预约、支持线上线下支付、实时评价、建议采集等功能,从而减少人力成本,方便客户享受快节奏、高品质的就餐点餐服务。
人可以掌握多门外语,而一个计算机科学家精通的大多是编程语言,它不是人类的自然语言,比如C语言、Java、Perl等等。由于不同的公司开发出的“中间件”不够规范,所以Sun公司推出J2EE,用这个标准来解决弊病。它提供了良好的机制,让每个层次允许与之相对的服务器、组件运行,使得系统的搭建稳定可用、开发高效、维护方便。
Springboot(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis两个开源框架整合而成(SpringMVC是Spring中的部分内容)。常作为数据源较简单的web项目的框架。
1.1Spring
Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象。也可以称之为项目中的粘合剂。
Spring的核心思想是IoC(控制反转),即不再需要程序员去显式地`new`一个对象,而是让Spring框架帮你来完成这一切。
1.2 SpringMVC
SpringMVC在项目中拦截用户请求,它的核心Servlet即DispatcherServlet承担中介或是前台这样的职责,将用户请求通过HandlerMapping去匹配Controller,Controller就是具体对应请求所执行的操作。SpringMVC相当于SSH框架中struts。
1.3 mybatis
mybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到各实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。
页面发送请求给控制器,控制器调用业务层处理逻辑,逻辑层向持久层发送请求,持久层与数据库交互,后将结果返回给业务层,业务层将处理逻辑发送给控制器,控制器再调用视图展现数据。
B/S(Browser/Server)比前身架构更为省事的架构。它借助Web server完成数据的传递交流。只需要下载浏览器作为客户端,那么工作就达到“瘦身”效果, 不需要考虑不停装软件的问题。
Spring框架是Java平台上的一种开源应用框架,提供具有控制反转特性的容器。尽管Spring框架自身对编程模型没有限制,但其在Java应用中的频繁使用让它备受青睐,以至于后来让它作为EJB(EnterpriseJavaBeans)模型的补充,甚至是替补。Spring框架为开发提供了一系列的解决方案,比如利用控制反转的核心特性,并通过依赖注入实现控制反转来实现管理对象生命周期容器化,利用面向切面编程进行声明式的事务管理,整合多种持久化技术管理数据访问,提供大量优秀的Web框架方便开发等等。Spring框架具有控制反转(IOC)特性,IOC旨在方便项目维护和测试,它提供了一种通过Java的反射机制对Java对象进行统一的配置和管理的方法。Spring框架利用容器管理对象的生命周期,容器可以通过扫描XML文件或类上特定Java注解来配置对象,开发者可以通过依赖查找或依赖注入来获得对象。Spring框架具有面向切面编程(AOP)框架,SpringAOP框架基于代理模式,同时运行时可配置;AOP框架主要针对模块之间的交叉关注点进行模块化。Spring框架的AOP框架仅提供基本的AOP特性,虽无法与AspectJ框架相比,但通过与AspectJ的集成,也可以满足基本需求。Spring框架下的事务管理、远程访问等功能均可以通过使用SpringAOP技术实现。Spring的事务管理框架为Java平台带来了一种抽象机制,使本地和全局事务以及嵌套事务能够与保存点一起工作,并且几乎可以在Java平台的任何环境中工作。Spring集成多种事务模板,系统可以通过事务模板、XML或Java注解进行事务配置,并且事务框架集成了消息传递和缓存等功能。Spring的数据访问框架解决了开发人员在应用程序中使用数据库时遇到的常见困难。它不仅对Java:JDBC、iBATS/MyBATIs、Hibernate、Java数据对象(JDO)、ApacheOJB和ApacheCayne等所有流行的数据访问框架中提供支持,同时还可以与Spring的事务管理一起使用,为数据访问提供了灵活的抽象。Spring框架最初是没有打算构建一个自己的WebMVC框架,其开发人员在开发过程中认为现有的StrutsWeb框架的呈现层和请求处理层之间以及请求处理层和模型之间的分离不够,于是创建了SpringMVC。
Mysql 经过多次的更新,功能层面已经非常的丰富和完善了,从Mysql4版本到5版本进行了比较大的更新,在商业的实际使用中取得了很好的实际应用效果。最新版本的Mysql支持对信息的压缩,同时还能进行加密能更好的满足对信息安全性的需求。同时经过系统的多次更新,数据库自身的镜像功能也得到了很大的增强,运行的流畅度和易用性方面有了不小的进步,驱动的使用和创建也更加的高效快捷。最大的变动还是进行了空间信息的显示优化,能更加方便的在应用地图上进行坐标的标注和运算。强大的备份功能也保证了用户使用的过程会更加安心,同时支持的Office特性还支持用户的自行安装和使用。在信息的显示形式上也进行了不小的更新,增加了两个非常使用的显示区,一个是信息区,对表格和文字进行了分类处理,界面的显示更加清爽和具体。第二是仪表的信息控件,能在仪表信息区进行信息的显示,同时还能进行多个信息的比对,为用户的实际使用带来了很大的便捷。
针对本文中设计的酒店会员点餐系统在实际的实现过程中,最终选择Mysql数据库的主要原因在于在企业的应用系统应用及开发的过程中会存在大量的数据库比较频繁的操作,而且数据的安全性要求也是非常的高。综合这些因素,最终选择安全性系数比较高的Mysql来对酒店会员点餐系统后台数据进行存储操作。
B/S架构采取浏览器请求,服务器响应的工作模式。
用户可以通过浏览器去访问Internet上由Web服务器产生的文本、数据、图片、动画、视频点播和声音等信息;
而每一个Web服务器又可以通过各种方式与数据库服务器连接,大量的数据实际存放在数据库服务器中;
从Web服务器上下载程序到本地来执行,在下载过程中若遇到与数据库有关的指令,由Web服务器交给数据库服务器来解释执行,并返回给Web服务器,Web服务器又返回给用户。在这种结构中,将许许多多的网连接到一块,形成一个巨大的网,即全球网。而各个企业可以在此结构的基础上建立自己的Internet。
在 B/S 模式中,用户是通过浏览器针对许多分布于网络上的服务器进行请求访问的,浏览器的请求通过服务器进行处理,并将处理结果以及相应的信息返回给浏览器,其他的数据加工、请求全部都是由Web Server完成的。通过该框架结构以及植入于操作系统内部的浏览器,该结构已经成为了当今软件应用的主流结构模式。
本系统将在经济、技术、操作这三个角度上进行可行性分析。
整个系统从设计到开发以及测试过程严谨步骤齐全,所有工作任务全部由本人完成,并未获取外部技术支持,节约了一切服务成本开销以及人工成本,在硬件方面,为节约成本使用一台二手移动工作站作为项目部署服务器以及数据库服务器,成本在一万元一下,真个网络部署也是由本人独立完成不涉及到其他人工费用,整个开发过程本着低成本,低消耗的原则。
技术可行性分析的目的是确认该系统能否利用现有技术实现,并评估开发效率和完成情况。技术的可行性是指在当前的技术条件下,计算机软件和硬件的开发是否能够满足发展的要求。因为该系统的开发基于Java语言,所以开发该系统所需的软件和硬件条件可以在普通计算机上满足。因为它占用的内存相对较少,所以用Mysql数据库开发和设计软件理论上没有问题,因为它占用的内存太少。上述技术可以有效地保证系统的成功和高效开发。
酒店会员点餐系统的使用界面简单易于操作,采用常见的界面窗口来登录界面,通过电脑进行访问操作,用户只要平时使用过电脑都能进行访问操作。此系统的开发采用Java技术开发,人性化和完善化是B/S结构开发比较显要的特点使得用户操作相比较其他更加简洁方便。易操作、易管理、交互性好在本系统操作上体现得淋漓尽致。
前台需求:
(1)用户模块:主要包括用户的注册和登陆、用户个人信息管理等功能。
(2)酒店资讯模块:主要包括酒店资讯信息浏览功能。
(3)酒店菜品模块:用户查看酒店菜品功能。
(4)酒店酒水模块:可以在线搜索酒水信息。
(5)酒店房间模块:查看酒店房间信息。
(6)下单模块:可以在线进行菜品下单、酒水下单等操作。
(7)房间预订模块:办理房间预订提交。
(8)餐桌预约详情:可以查看餐桌预约信息等。
后台需求:
(1)用户管理:主要包括用户列表、用户等级管理等功能。
(2)酒店菜品管理:主要包括菜品信息的管理维护等。
(3)酒店酒水管理:主要包括酒水信息的管理维护等
(4)下单管理:对用户的餐品以及酒水订单进行审核处理。
(4)房间管理:维护管理酒店房间信息。
(5)房间预约管理:审核用户的房间预约业务。
(6)餐桌预约管理。
用户用例图如下所示。
图1 用户用例图
管理员用例图如下所示。
图2 管理员用例图
菜品添加用例描述如下表所示。
表1菜品添加用例描述
用例名称 |
添加新菜品 |
|
参与者 |
管理员 |
|
用例概述 |
本用例用于管理员进行添加新菜品操作 |
|
前置条件 |
管理员添加新菜品前必须登录系统 |
|
后置条件 |
系统中添加一个新菜品 |
|
基本事件流 |
参与者动作 |
系统响应 |
4、管理员填写新菜品信息,点击“添加”按钮。 |
2、系统打开添加新菜品界面。 3、系统检查管理员输入的菜品信息是正确有效的。 5、系统将菜品添加到数据库中。 6、系统提示“操作成功”。 7、系统跳转到菜品管理界面。 |
|
其他事件流 |
系统验证管理员输入的菜品名为空,则提示“*请填写菜品名称!”。 |
酒店房间删除用例描述如下表所示。
表2酒店房间删除用例描述
用例名称 |
删除酒店房间 |
|
参与者 |
管理员 |
|
用例概述 |
本用例用于管理员进行删除酒店房间操作 |
|
前置条件 |
管理员删除酒店房间前必须登录系统 |
|
后置条件 |
系统中删除一个酒店房间 |
|
基本事件流 |
参与者动作 |
系统响应 |
1、管理员在后台主界面选择“酒店房间管理”。 4、管理员选择一个酒店房间,点击“删除”按钮。 6、管理员点击“确定”按钮。 |
2、系统从数据库中获取酒店房间信息列表 3、系统打开酒店房间列表界面。 5、系统提示“你确定要删除吗?”。 7、系统将酒店房间从数据库中删除。 8、系统提示“删除成功”。 9、系统跳转到酒店房间管理界面。 |
|
其他事件流 |
无 |
用户编辑用例描述如下表所示。
表3用户编辑用例描述
用例名称 |
修改用户 |
|
参与者 |
管理员 |
|
用例概述 |
本用例用于管理员进行修改用户信息操作 |
|
前置条件 |
管理员已经登录系统 |
|
后置条件 |
系统中更新一条用户记录 |
|
基本事件流 |
参与者动作 |
系统响应 |
1、管理员在后台主界面选择“用户管理”。 4、管理员在用户列表中选择一个用户,点击“编辑”按钮。 6、管理员填写用户信息,点击“保存修改”按钮。 |
2、系统从数据库中获取用户信息。 3、系统打开用户列表界面。 5、系统打开修改用户信息界面。 7、系统将更改后的添加到数据库中。 8、系统提示“操作成功”。 9、系统跳转到用户管理界面。 |
|
其他事件流 |
无 |
菜品下单用例描述如下表所示。
表4菜品下单用例描述
用例名称 |
菜品下单 |
|
参与者 |
用户 |
|
用例概述 |
本用例用于用户进行对菜品下单操作 |
|
前置条件 |
用户已经登录系统 |
|
后置条件 |
系统中增加一条用户签订记录 |
|
基本事件流 |
参与者动作 |
系统响应 |
1、用户在前台首页选择任意一个菜品分类。 4、管理员在用户列表中选择一个菜品。 7、用户选择菜品,点击“下单”按钮。 |
2、系统从数据库中获取菜品列表信息。 3、系统打开菜品列表界面。 5、系统从数据库中获取菜品信息。 6、系统打开菜品信息界面。 8、系统检查用户输入的信息是正确有效的。 |
|
其他事件流 |
1、系统验证用户输入的字段为空,则提示“*菜品信息不能为空!”。 |
随着用户量的增加,系统可能会需要同时服务上千、上万个页面,服务器需要同时响应大量用户的操作,这就要求系统需要有良好的可扩展性,否则系统会出现延迟,卡顿甚至服务器崩溃的问题。高扩展性可以使软件保持旺盛的生命力,同时也能够使系统更好的适应用户增加、提高性能需求、增加应用功能等改变。
系统中保存了大量用户和管理员的个人信息,因此,保证系统服务器和数据安全是在开发过程中需要考虑的重要问题。安全性包括服务器安全、操作系统安全、数据库安全、程序代码安全以及用户个人信息和支付安全等,系统可以通过采用防火墙技术、加密技术、认证技术等来增强其安全性,只有一个健壮安全的系统才能具有长久的生命力。
酒店会员点餐系统的前台中,用户模块主要实现菜品下单、酒水下单、房间预约的功能。酒店会员点餐系统的后台中,管理员对用户在前台提交产生的数据进行处理,以满足用户的需求。前台系统和后台系统有数据交互,整个系统各个部分相互独立又密不可分。后台的功能主要包括用户管理、酒店房间管理、房间预约管理、餐品下单管理、酒水下单管理、酒店房间管理等。
通过软件的需求分析已经获得了系统的基本功能需求。根据各大功能模块的不同,将系统分为各种功能大块。系统功能结构如下图所示。
图4系统功能结构图
概念设计包括实体和联系两部分,如该系统中,用户是一个实体,其属性包括用户 ID 标识、用户名、密码、电话、地址等属性。联系是指实体之间有意义的关联,包括一对一、一对多、多对多三种类型。
系统E-R图如下所示。
图5系统E-R图
连接数据库的文件在Resources 文件夹下的application.yml文件,代码如下:
server:
port: 5000
servlet:
context-path: /api
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/CS725260_20211101091736?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
jackson:
property-naming-strategy: CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
default-property-inclusion: ALWAYS
time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB
数据库表是设计和实现系统的一个重要基础。以下列出了酒店会员点餐系统几个重要的数据库表。
名称 |
类型 |
长度 |
不是null |
主键 |
注释 |
hotel_dishes_id |
int |
11 |
是 |
是 |
酒店菜品ID |
dish_name |
varchar |
64 |
否 |
否 |
菜品名称 |
cuisine_category |
varchar |
64 |
否 |
否 |
菜品类系 |
dish_pictures |
varchar |
255 |
否 |
否 |
菜品图片 |
dish_price |
varchar |
64 |
否 |
否 |
菜品价格 |
remarks |
varchar |
64 |
否 |
否 |
备注 |
dish_details |
text |
0 |
否 |
否 |
菜品详情 |
hits |
int |
11 |
是 |
否 |
点击数 |
praise_len |
int |
11 |
是 |
否 |
点赞数 |
recommend |
int |
11 |
是 |
否 |
智能推荐 |
create_time |
datetime |
0 |
是 |
否 |
创建时间 |
update_time |
timestamp |
0 |
是 |
否 |
更新时间 |
名称 |
类型 |
长度 |
不是null |
主键 |
注释 |
hotel_drinks_id |
int |
11 |
是 |
是 |
酒店酒水ID |
wine_name |
varchar |
64 |
否 |
否 |
酒水名称 |
beverage_type |
varchar |
64 |
否 |
否 |
酒水类型 |
wine_picture |
varchar |
255 |
否 |
否 |
酒水图片 |
wine_price |
varchar |
64 |
否 |
否 |
酒水价格 |
remarks |
varchar |
64 |
否 |
否 |
备注 |
drinks_details |
text |
0 |
否 |
否 |
酒水详情 |
hits |
int |
11 |
是 |
否 |
点击数 |
praise_len |
int |
11 |
是 |
否 |
点赞数 |
recommend |
int |
11 |
是 |
否 |
智能推荐 |
create_time |
datetime |
0 |
是 |
否 |
创建时间 |
update_time |
timestamp |
0 |
是 |
否 |
更新时间 |
名称 |
类型 |
长度 |
不是null |
主键 |
注释 |
hotel_room_id |
int |
11 |
是 |
是 |
酒店房间ID |
room_name |
varchar |
64 |
否 |
否 |
房间名称 |
room_type |
varchar |
64 |
否 |
否 |
房间类型 |
room_picture |
varchar |
255 |
否 |
否 |
房间图片 |
room_price |
varchar |
64 |
否 |
否 |
房间价格 |
remarks |
varchar |
64 |
否 |
否 |
备注 |
room_details |
text |
0 |
否 |
否 |
房间详情 |
hits |
int |
11 |
是 |
否 |
点击数 |
praise_len |
int |
11 |
是 |
否 |
点赞数 |
recommend |
int |
11 |
是 |
否 |
智能推荐 |
create_time |
datetime |
0 |
是 |
否 |
创建时间 |
update_time |
timestamp |
0 |
是 |
否 |
更新时间 |
名称 |
类型 |
长度 |
不是null |
主键 |
注释 |
hotel_table_id |
int |
11 |
是 |
是 |
酒店餐桌ID |
table_number |
varchar |
64 |
否 |
否 |
餐桌编号 |
table_area |
varchar |
64 |
否 |
否 |
餐桌区域 |
table_size |
varchar |
64 |
否 |
否 |
餐桌规模 |
table_pictures |
varchar |
255 |
否 |
否 |
餐桌图片 |
remarks |
text |
0 |
否 |
否 |
备注 |
hits |
int |
11 |
是 |
否 |
点击数 |
praise_len |
int |
11 |
是 |
否 |
点赞数 |
recommend |
int |
11 |
是 |
否 |
智能推荐 |
create_time |
datetime |
0 |
是 |
否 |
创建时间 |
update_time |
timestamp |
0 |
是 |
否 |
更新时间 |
名称 |
类型 |
长度 |
不是null |
主键 |
注释 |
order_dishes_id |
int |
11 |
是 |
是 |
菜品下单ID |
dish_name |
varchar |
64 |
否 |
否 |
菜品名称 |
cuisine_category |
varchar |
64 |
否 |
否 |
菜品类系 |
dish_price |
varchar |
64 |
否 |
否 |
菜品价格 |
purchase_quantity |
varchar |
64 |
否 |
否 |
购买数量 |
purchase_user |
int |
11 |
否 |
否 |
购买用户 |
member_discount |
varchar |
64 |
否 |
否 |
会员折扣 |
total_price |
varchar |
64 |
否 |
否 |
共计价格 |
pay_state |
varchar |
16 |
是 |
否 |
支付状态 |
pay_type |
varchar |
16 |
否 |
否 |
支付类型 |
recommend |
int |
11 |
是 |
否 |
智能推荐 |
create_time |
datetime |
0 |
是 |
否 |
创建时间 |
update_time |
timestamp |
0 |
是 |
否 |
更新时间 |
名称 |
类型 |
长度 |
不是null |
主键 |
注释 |
ordinary_users_id |
int |
11 |
是 |
是 |
普通用户ID |
user_name |
varchar |
64 |
否 |
否 |
用户姓名 |
user_gender |
varchar |
64 |
否 |
否 |
用户性别 |
membership_level |
varchar |
64 |
否 |
否 |
会员等级 |
member_discount |
varchar |
64 |
否 |
否 |
会员折扣 |
examine_state |
varchar |
16 |
是 |
否 |
审核状态 |
recommend |
int |
11 |
是 |
否 |
智能推荐 |
user_id |
int |
11 |
是 |
否 |
用户ID |
create_time |
datetime |
0 |
是 |
否 |
创建时间 |
update_time |
timestamp |
0 |
是 |
否 |
更新时间 |
名称 |
类型 |
长度 |
不是null |
主键 |
注释 |
room_reservation_id |
int |
11 |
是 |
是 |
房间预订ID |
room_name |
varchar |
64 |
否 |
否 |
房间名称 |
room_type |
varchar |
64 |
否 |
否 |
房间类型 |
room_price |
varchar |
64 |
否 |
否 |
房间价格 |
booking_quantity |
varchar |
64 |
否 |
否 |
预订数量 |
booking_date |
date |
0 |
否 |
否 |
预订日期 |
purchase_user |
int |
11 |
否 |
否 |
购买用户 |
member_discount |
varchar |
64 |
否 |
否 |
会员折扣 |
total_price |
varchar |
64 |
否 |
否 |
共计价格 |
pay_state |
varchar |
16 |
是 |
否 |
支付状态 |
pay_type |
varchar |
16 |
否 |
否 |
支付类型 |
recommend |
int |
11 |
是 |
否 |
智能推荐 |
create_time |
datetime |
0 |
是 |
否 |
创建时间 |
update_time |
timestamp |
0 |
是 |
否 |
更新时间 |
名称 |
类型 |
长度 |
不是null |
主键 |
注释 |
table_reservation_id |
int |
11 |
是 |
是 |
餐桌预约ID |
table_number |
varchar |
64 |
否 |
否 |
餐桌编号 |
table_size |
varchar |
64 |
否 |
否 |
餐桌规模 |
reservation_user |
int |
11 |
否 |
否 |
预约用户 |
time_of_appointment |
time |
0 |
否 |
否 |
预约时间 |
remarks |
varchar |
64 |
否 |
否 |
备注 |
recommend |
int |
11 |
是 |
否 |
智能推荐 |
create_time |
datetime |
0 |
是 |
否 |
创建时间 |
update_time |
timestamp |
0 |
是 |
否 |
更新时间 |
名称 |
类型 |
长度 |
不是null |
主键 |
注释 |
wine_order_id |
int |
11 |
是 |
是 |
酒水下单ID |
wine_name |
varchar |
64 |
否 |
否 |
酒水名称 |
beverage_type |
varchar |
64 |
否 |
否 |
酒水类型 |
wine_price |
varchar |
64 |
否 |
否 |
酒水价格 |
purchase_quantity |
varchar |
64 |
否 |
否 |
购买数量 |
purchase_user |
int |
11 |
否 |
否 |
购买用户 |
member_discount |
varchar |
64 |
否 |
否 |
会员折扣 |
total_price |
varchar |
64 |
否 |
否 |
共计价格 |
pay_state |
varchar |
16 |
是 |
否 |
支付状态 |
pay_type |
varchar |
16 |
否 |
否 |
支付类型 |
recommend |
int |
11 |
是 |
否 |
智能推荐 |
create_time |
datetime |
0 |
是 |
否 |
创建时间 |
update_time |
timestamp |
0 |
是 |
否 |
更新时间 |
用户注册完成后,点击“登陆”进入到登陆页面,输入用户名和密码,点击“登陆”按钮,对用户名和密码进行验证,根据传入的用户名和密码在数据库中是否能查询到一条用户信息,若不能返回用户信息则登陆失败,页面提示用户名或密码错误。
登陆拦截管理器,在config文件夹下的WebAppConfig.java文件,代码如下:
@Configuration
@Slf4j
public class WebAppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//登录拦截的管理器
InterceptorRegistration registration = registry.addInterceptor(loginInterceptor());
//拦截的地址
registration.addPathPatterns("/**");
//方行的地址
//registration.excludePathPatterns("/**");
//根据需要拦截,一般设置所有地址拦截,放行公共连接
}
@Bean
public LoginInterceptor loginInterceptor(){
return new LoginInterceptor();
}
}
登录界面如下图所示。
图5-1登录界面
用户登录的关键代码如下。
/**
* 登录
* @param data
* @param httpServletRequest
* @return
*/
@PostMapping("login")
public Map
log.info("[执行登录接口]");
String username = data.get("username");
String email = data.get("email");
String phone = data.get("phone");
String password = data.get("password");
List resultList = null;
Map
if(username != null && "".equals(username) == false){
map.put("username", username);
resultList = service.select(map, new HashMap<>()).getResultList();
}
else if(email != null && "".equals(email) == false){
map.put("email", email);
resultList = service.select(map, new HashMap<>()).getResultList();
}
else if(phone != null && "".equals(phone) == false){
map.put("phone", phone);
resultList = service.select(map, new HashMap<>()).getResultList();
}else{
return error(30000, "账号或密码不能为空");
}
if (resultList == null || password == null) {
return error(30000, "账号或密码不能为空");
}
//判断是否有这个用户
if (resultList.size()<=0){
return error(30000,"用户不存在");
}
User byUsername = (User) resultList.get(0);
Map
groupMap.put("name",byUsername.getUserGroup());
List groupList = userGroupService.select(groupMap, new HashMap<>()).getResultList();
if (groupList.size()<1){
return error(30000,"用户组不存在");
}
UserGroup userGroup = (UserGroup) groupList.get(0);
//查询用户审核状态
if (!StringUtils.isEmpty(userGroup.getSourceTable())){
String sql = "select examine_state from "+ userGroup.getSourceTable() +" WHERE user_id = " + byUsername.getUserId();
String res = String.valueOf(service.runCountSql(sql).getSingleResult());
if (res==null){
return error(30000,"用户不存在");
}
if (!res.equals("已通过")){
return error(30000,"该用户审核未通过");
}
}
//查询用户状态
if (byUsername.getState()!=1){
return error(30000,"用户非可用状态,不能登录");
}
String md5password = service.encryption(password);
if (byUsername.getPassword().equals(md5password)) {
// 存储Token到数据库
AccessToken accessToken = new AccessToken();
accessToken.setToken(UUID.randomUUID().toString().replaceAll("-", ""));
accessToken.setUser_id(byUsername.getUserId());
tokenService.save(accessToken);
// 返回用户信息
JSONObject user = JSONObject.parseObject(JSONObject.toJSONString(byUsername));
user.put("token", accessToken.getToken());
JSONObject ret = new JSONObject();
ret.put("obj",user);
return success(ret);
} else {
return error(30000, "账号或密码不正确");
}
}
用户界面要尽量简洁大方,使用户能够方便找到需要的功能入口,浏览酒店资讯、酒店菜品、酒店酒水、酒店房间、菜品下单、房间预订等,且要易于修改和维护,同时还要保证用户合法和系统安全。
首页界面如下图所示。
图5-2首页界面
用户进入系统首页后,点击“注册”链接进入到注册页面,按照页面提示输入用户名密码和手机号,页面进行表单验证,验证输入的用户名和账号是否合法,表单验证通过后,点击“立即注册”按钮,利用 Ajax 技术,对用户名和账号实现页面无刷新验证,检测数据库中是否已经存在该用户名,若数据库中不存在,则注册成功,注册成功后,自动跳转到登录页面。
用户注册逻辑代码如下:
/**
* 注册
* @param user
* @return
*/
@PostMapping("register")
public Map
// 查询用户
Map
query.put("username",user.getUsername());
List list = service.select(query, new HashMap<>()).getResultList();
if (list.size()>0){
return error(30000, "用户已存在");
}
user.setUserId(null);
user.setPassword(service.encryption(user.getPassword()));
service.save(user);
return success(1);
}
/**
* 用户ID:[0,8388607]用户获取其他与用户相关的数据
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Integer userId;
/**
* 账户状态:[0,10](1可用|2异常|3已冻结|4已注销)
*/
@Basic
@Column(name = "state")
private Integer state;
/**
* 所在用户组:[0,32767]决定用户身份和权限
*/
@Basic
@Column(name = "user_group")
private String userGroup;
/**
* 上次登录时间:
*/
@Basic
@Column(name = "login_time")
private Timestamp loginTime;
/**
* 手机号码:[0,11]用户的手机号码,用于找回密码时或登录时
*/
@Basic
@Column(name = "phone")
private String phone;
/**
* 手机认证:[0,1](0未认证|1审核中|2已认证)
*/
@Basic
@Column(name = "phone_state")
private Integer phoneState;
/**
* 用户名:[0,16]用户登录时所用的账户名称
*/
@Basic
@Column(name = "username")
private String username;
/**
* 昵称:[0,16]
*/
@Basic
@Column(name = "nickname")
private String nickname;
/**
* 密码:[0,32]用户登录所需的密码,由6-16位数字或英文组成
*/
@Basic
@Column(name = "password")
private String password;
/**
* 邮箱:[0,64]用户的邮箱,用于找回密码时或登录时
*/
@Basic
@Column(name = "email")
private String email;
/**
* 邮箱认证:[0,1](0未认证|1审核中|2已认证)
*/
@Basic
@Column(name = "email_state")
private Integer emailState;
/**
* 头像地址:[0,255]
*/
@Basic
@Column(name = "avatar")
private String avatar;
/**
* 创建时间:
*/
@Basic
@Column(name = "create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Timestamp createTime;
@Basic
@Transient
private String code;
}
酒店菜品页面,用户可以浏览菜品信息包括:菜品名称、菜品类系、菜品价格等。如下图所示。
图5-3酒店菜品页面
酒店菜品的关键代码如下。
@PostMapping("/add")
@Transactional
public Map
service.insert(service.readBody(request.getReader()));
return success(1);
}
@Transactional
public Map
service.insert(map);
return success(1);
}
public Map
BufferedReader br = null;
StringBuilder sb = new StringBuilder("");
try{
br = reader;
String str;
while ((str = br.readLine()) != null){
sb.append(str);
}
br.close();
String json = sb.toString();
return JSONObject.parseObject(json, Map.class);
}catch (IOException e){
e.printStackTrace();
}finally{
if (null != br){
try{
br.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
return null;
}
public void insert(Map
StringBuffer sql = new StringBuffer("INSERT INTO ");
sql.append("`").append(table).append("`").append(" (");
for (Map.Entry
sql.append("`"+humpToLine(entry.getKey())+"`").append(",");
}
sql.deleteCharAt(sql.length()-1);
sql.append(") VALUES (");
for (Map.Entry
Object value = entry.getValue();
if (value instanceof String){
sql.append("'").append(entry.getValue()).append("'").append(",");
}else {
sql.append(entry.getValue()).append(",");
}
}
sql.deleteCharAt(sql.length() - 1);
sql.append(")");
log.info("[{}] - 插入操作:{}",table,sql);
Query query = runCountSql(sql.toString());
query.executeUpdate();
}
系统首页提供了菜品下单信息的输入框,用户在输入框内输入具体的下单信息,点击提交按钮,系统将用户下单的菜品信息传递到后台。首先创建一个实体类 PageBean,该实体类的属性包括页码 pageCode、每页记录数 pageSize、总记录数 totalRecord 和一个 List 集合 beanList,用循环将搜索到的结果分页展示。
菜品下单界面如下图所示。
图5-4菜品下单界面
菜品下单的关键代码如下。
@RequestMapping(value = {"/avg_group", "/avg"})
public Map
Query count = service.avg(service.readQuery(request), service.readConfig(request));
return success(count.getResultList());
}
酒水下单界面如下图所示。
图5-5酒水下单界面
酒水下单的关键代码:
@RestController
@RequestMapping("auth")
public class AuthController extends BaseController
/**
* 服务对象
*/
@Autowired
public AuthController(AuthService service) {
setService(service);
}
}
管理员对系统用户的管理,在管理员管理实现管理员用户的管理,包括录入、删除、修改,修改密码通过SESSION获取用户名,然后输入新密码,使用sql命令更新密码。
用户管理界面如下图所示。
图5-6用户管理界面
管理员可以获取系统中所有宽带用户费用列表,并可以对其信息进行编辑。管理员在添加房间预订时,需要输入用户信息、缴费账号、计费类型、金额等,并对其进行维护管理等。
房间预订管理界面如下图所示。
图5-7房间预订管理界面
房间预订管理关键代码:
@RequestMapping("/get_obj")
public Map
Query select = service.select(service.readQuery(request), service.readConfig(request));
List resultList = select.getResultList();
if (resultList.size() > 0) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("obj",resultList.get(0));
return success(jsonObject);
} else {
return success(null);
}
}
public Query select(Map
StringBuffer sql = new StringBuffer("select ");
sql.append(config.get(FindConfig.FIELD) == null || "".equals(config.get(FindConfig.FIELD)) ? "*" : config.get(FindConfig.FIELD)).append(" ");
sql.append("from ").append("`").append(table).append("`").append(toWhereSql(query, "0".equals(config.get(FindConfig.LIKE))));
if (config.get(FindConfig.GROUP_BY) != null && !"".equals(config.get(FindConfig.GROUP_BY))){
sql.append("group by ").append(config.get(FindConfig.GROUP_BY)).append(" ");
}
if (config.get(FindConfig.ORDER_BY) != null && !"".equals(config.get(FindConfig.ORDER_BY))){
sql.append("order by ").append(config.get(FindConfig.ORDER_BY)).append(" ");
}
if (config.get(FindConfig.PAGE) != null && !"".equals(config.get(FindConfig.PAGE))){
int page = config.get(FindConfig.PAGE) != null && !"".equals(config.get(FindConfig.PAGE)) ? Integer.parseInt(config.get(FindConfig.PAGE)) : 1;
int limit = config.get(FindConfig.SIZE) != null && !"".equals(config.get(FindConfig.SIZE)) ? Integer.parseInt(config.get(FindConfig.SIZE)) : 10;
sql.append(" limit ").append( (page-1)*limit ).append(" , ").append(limit);
}
log.info("[{}] - 查询操作,sql: {}",table,sql);
return runEntitySql(sql.toString());
}
管理员在后台管理界面点击到所有酒水订单界面,可以搜索当前所有订单信息,向数据库搜索当前所有酒水订单并将下单信息以对象的形式层层返回到酒水下单界面,显示出当前所有酒水下单信息。同时可以删除过期酒水下单,确认已有酒水下单。
酒水下单管理界面如下图所示。
图5-8酒水下单管理界面
酒水下单管理的关键代码如下。
@RequestMapping(value = {"/avg_group", "/avg"})
public Map
Query count = service.avg(service.readQuery(request), service.readConfig(request));
return success(count.getResultList());
}
以进入系统首页的访问速度为例展示系统的性能测试;系统的主要用户群体是购物理念较为先进的消费者,系统要在3秒钟内响应;需要完成页面的菜单栏、首页轮播图片、类目及菜品列表、菜品评价以及各功能模块入口等元素的显示。
功能性测试是指执行指定的工作流程,通过对一个系统的所有特性和功能都进行测试确保符合需求和规范。
系统功能性测试表如下表所示。
表11系统功能性测试表
编号 |
测试功能 |
测试内容 |
测试结果 |
1 |
用户登录 |
1.验证用户名与密码的正确性。 2.验证密码是否可见。 |
通过 |
2 |
首页展示 |
1.首页数据是否成功加载。 2.验证搜索功能的准确性。 3.验证是否可以异步加载。 4.验证导航栏按钮。 |
通过 |
3 |
个人信息修改 |
1.验证登录名是否可以正常更改。 2.验证联系方式是否可以更改。 3.验证收货地址可以正常修改。 4.验证密码是否可以修改。 |
通过 |
4 |
酒店菜品管理 |
1.菜品清单是否可以生成。 2.验证消费信息是否准确。 |
通过 |
7 |
酒店资讯管理 |
1.验证资讯新增是否可以成功。 2.验证资讯删除是否可以成功。 |
通过 |
8 |
菜品下单管理 |
1.菜品信息是否与上传一致。 2.是否能完成下单。 |
通过 |
9 |
酒水信息 |
1.能否正常上传酒水信息。 2.验证数据准确性。 |
通过 |
10 |
房间预约 |
1.上传预约信息是否添加验证。 2.验证表单是否提交成功。 |
通过 |
11 |
用户管理 |
1.验证用户录入功能。 2.验证用户违规清理功能。 |
通过 |
集成测试后,所有的模块已经全部连接完毕,形成了一个完整的系统。合格性测试是在集成测试完毕后,进一步对系统进行综合性的检测。经过合格性测试,可以检查出系统是否符合系统的设计,能够完成需求的所有功能。本系统经过最后的测试,所有模块功能都能按预定要求工作。
在实际测试中,经过一系列系统性的测试,使我们能够及时发现一些系统在设计中出现的疏忽和漏洞。经过严密的测试,不仅发现了模块内部的错误,也查找到模块连接后产生的错误。经过测试,对系统产生错误的地方进行优化、修改和完善,使得系统能够实现最初设计的基本功能。
本文针对酒店会员点餐系统的特点和用户需求,利用 Java相关技术、Springboot框架和等技术,通过详细的需求分析、页面设计和功能设计,系统利用JQuery 技术和 CSS 技术进行了页面设计,实现了包括用户模块、酒店菜品模块、酒店酒水模块。下单模块和房间预订模块的前台系统以及包括用户管理模块、菜品下单管理模块、酒水下单管理模块的后台系统。并添加了用户的访问控制,建立了一个完整、健壮、安全稳定的酒店会员点餐系统。
由于时间限制和本人能力条件有限,还存在一些不足,今后也会出现许多新的开发技术,未来还可以对程序做出如下改进:
(1)优化程序页面,使页面更加美观且方便操作;
(2)优化信息搜索功能,提供多条件选择查询搜索;
(3)优化分类功能,提高分类的精准度;
(4)进一步提高使用程序的安全性,使其更加健壮;
(5)优化数据和代码,提升软件效率,方便维护和扩展。
[1]黄成谋,施键兰. 手机自助点餐系统设计[J]. 软件,2019,40(04):31-34.
[2]霍涛,山宇韬,王俊豪. 基于J2EE的网络点餐系统设计与实现[J]. 科技风,2019(22):98.
[3]赵泽忠,程江珂. 基于移动端的智能点餐系统设计与实现[J]. 电脑知识与技术,2019,15(17):113-114.
[4]陈南平. 基于SOA架构的移动Web点餐系统设计与实现[J]. 信息与电脑(理论版),2020,32(03):49-52.
[5]古入次仁,陈浩,索南尖措. 基于SSM和Java的校园点餐系统[J]. 中国高新科技,2020(14):122-123.
[6]涂敦兰,王莎. 基于Wi-Fi的智能点餐系统[J]. 电信快报,2020(10):41-43.
[7]杨凯,赵晓梅,杨倩倩,周雅婕,赵磊. 基于微信的高校食堂点餐系统[J]. 产业科技创新,2020,2(19):57-58.
[8]崔幸,苑广兴. 医院智慧营养膳食移动点餐系统[J]. 信息化建设,2021(04):59.
[9]黄健. 基于C#的餐厅点餐系统研究与设计[J]. 电脑知识与技术,2017,13(28):129-132+134.
[10]王慧媛. 扫码点餐系统的设计与分析[J]. 电子技术与软件工程,2020(23):50-51.
[11]冯秀玲. 智能点餐系统设计与应用[J]. 电子技术,2021,50(06):30-32.
[12]鹿俊聪. 基于Android的食堂点餐系统的设计与实现[J]. 科学技术创新,2021(22):101-102.
[13]韦娟,张瑞娟,孙兆丰. 基于微信小程序的食堂点餐系统的设计[J]. 电子世界,2019(22):147-148.
[14]张勇. 基于Android的智能点餐系统设计[J]. 电子测试,2017(22):71-72.
[15]刘丽. 基于Android平台的点餐系统设计与实现[J]. 信息与电脑(理论版),2018(15):117-118+122.
[16]杭莉,聂莉娟. 基于微信小程序的点餐系统[J]. 电子制作,2019(23):54-58.
时光飞逝,转眼间我在学校的这些年生活即将结束,回顾这几年的学习生活,收获良多,既有幸福也有难过,学校生活的结束对于我来说也是一个新的开始。论文即将完成,在此,我心中有许多想要感谢的人。首先感谢我的导师,不仅在学习研究方面加以指导,也在生活和为人处世上给予帮助。还要感谢授课老师,你们严谨的学术精神和积极向上的工作态度都在激励我的成长和进步。感谢多年来一直生活在一起的室友,谢谢你们多年来的陪伴和照顾。最后,要感谢各位论文评审老师,感谢您们在百忙之中抽空评阅本论文并给出宝贵的意见和建议。
免费领取本源代码,请关注点赞+私信