课程设计-点餐系统

1 系统分析 1
1.1需求来源 1
1.2用例设计 1
1.3功能描述 1
1.4非功能性需求 2
1.5竞品分析 2
2 系统设计 3
2.1架构设计 3
2.2结构设计 4
3 开发工具和运行环境 5
1、开发工具 5
2、运行环境 5
4 详细设计与实现 5
4.1数据库设计 5
4.2类的设计 11
4.3具体功能实现 16
5 系统测试 26
5.1功能测试 26
5.2 性能测试 31
6 总结 34
6.1问题和解决 34
6.2改进设想 35
6.3心得体会 35
7 参考文献 36

1 系统分析
1.1需求来源
通过对传统餐饮行业的研究,发现具有排队时间长、点餐时间长、座位冲突、服务员冲突的问题,极大地降低了顾客的用餐体验。本项目旨在为某一个具体的餐馆量身定做一个在线的点餐系统,并借鉴当下流行的在线平台进行分析和设计。
1.2用例设计
经过简单的需求分析,本系统用例图设计如图1.1所示。

图 1.1 顾客点餐流程图
1.3功能描述
顾客
(1)菜品浏览模块:顾客点击不同的分类,页面显示相应的菜品。
(2)菜品加购模块:顾客选择某个菜品和订购数量,选择加购之后,就会添加到当前订单中。
(3)结账模块:顾客浏览所选择的菜品,进行某一项的删除,可以有选择性的给老板留言。点击立即结账后,系统显示订单号、总计消费。
(4)订单模块:顾客可以查看自己的订单及状态。
(5)申请退款模块:顾客在结账后,由于某种原因,需要退款。
(6)评价功能:在一单交易完成后,顾客能够对订单进行满意度评价。
商家
(1)菜品管理模块:商家可以进行菜品的浏览、检索、添加、编辑、删除。
(2)分类管理模块:商家可以进行菜品分类的添加、编辑、删除。
(3)退款模块:商家可以对申请退款的订单进行退款。
(4)订单模块:商家能够浏览订单数、订单状态,以及可以查询某个时间段的订单。
1.4非功能性需求
(1) 可读性:代码编写规范。代码按照Java编程规范撰写,注释适当易懂,函数大小适中。
(2)可修改性:内聚性高、耦合低、易重构。类的封装有根据,类之间的关系明确,类和接口设计符合单一职责原则。
(3)易用性:操作页面简洁清晰,界面设置友好。
(4)响应时间短:对于每个请求,用户能在较短时间内收到响应信息。
1.5竞品分析
表 1.1竞品分析
产品 饿了么 美团
市场份额(2018-2019上半年) 32.8% 65.1%
视觉分析 蓝色主体、辨识度高 黄色主体、配色统一
交互分析 操作步数少 模块清晰、种类繁多
功能分析 专注外卖,创新功能较多 扩展应用较多,涵盖骑行、酒店住宿、电影、火车票/机票
核心竞争 背靠阿里,高效的物流管理、较高的用户满意度 背靠腾讯,利用大众社交刺激消费

2 系统设计
2.1架构设计
SpringMVC是当下流行的Java框架之一,同时也引入二级缓存。在点餐系统中使用本地redis缓存,可以提高性能;springboot省去了很多配置文件。

图 2.1 MVC架构
视图层选用jsp,控制层用基于注解的Controller,并增加了业务层;在dao层引入了mybatis框架,在application.properties文件中MySQL数据库。基于注解的方式,省去了很多配置文件信息,与此同时,代码不再依赖于具体的数据库,提高了代码的可修改性。
2.2结构设计
由需求分析可得,系统主要模块如图 2.2 所示,大致分为顾客模块和商家模块,具有明显的权限区分。
图 2.2 系统的主要模块
3 开发工具和运行环境
1、开发工具
编程语言:Java
前、后台开发工具:IDEA
数据库发开工具:Navicat
测试工具:Jmeter(性能测试),Selenium(web自动化测试),Junit(单元测试)
2、运行环境
硬件需求:
CPU:Intel® Core™ i5-7300HQ @ 2.50GHz 2.50GHz
内存: Samsung 8.0 GB
软件需求:
操作系统版本:Windows 10
后台服务器:Apache Tomcat 9.0
数据库版本:Mysql8.0
浏览器:Google Chrome

4 详细设计与实现
4.1数据库设计
4.1.1概念结构设计
(1)顾客实体和商家实体 E-R 图如图 4.1和 4.2 所示,虽然两个实体具有的属性相同,但是权限不一样。

图 4.1顾客实体E-R图 图 4.2商家实体E-R图
(2)分类实体和菜品实体 E-R 图如图 4.3 和 4.4所示。

图 4.3分类实体E-R图 图 4.4菜品实体E-R图
(3)订单项实体和订单实体 E-R 图如图4.5和4.6所示。

图 4.5订单项实体E-R图 图 4.6订单实体E-R图
(4)评价实体 E-R 图如图4.7所示。

图 4.7评价实体E-R图
(5)系统整体 E-R 图如图 4.8所示,图中省略了各个实体的属性,只保留了实体和实体之间的联系以及关系。

图 4.8系统整体E-R图
4.1.2逻辑结构设计
关系模型
(1)商家(账户、密码、姓名、电话)
(2)顾客(账户、密码、姓名、电话)
(3)分类(编号、名称)
(4)座位(桌号、座位号、状态)
(5)菜品(编号、分类编号、名称、单价、描述、图片)
(6)订单项(编号、订单编号、菜品编号、订购数量、小计)
(7)订单(编号、顾客账户、总额、日期、状态、备注)
基本表的设计
根据 E-R 模型和关系模型,点餐系统建立了 9 个基本表和两个视图,下面是各视图和基本表的详细说明。
(1)customer表主要是记录了顾客的基本信息,表结构设计如表4.1所示。

表 4.1顾客表

(2)merchant表主要是记录了商家的基本信息,表结构设计如表4.2所示。
表 4.2商家表

(3)dish表主要是记录了菜品的基本信息。表结构设计如表4.3所示。dish表中的外键约束:categoryNum属性参照category表的主键(num)。
表 4.3菜品表

(5)category表主要是记录了菜品分类的基本信息,表结构设计如表4.4所示。
表 4.4菜品分类表

(6)Lineitem表主要是记录了订单项的基本信息。表结构设计如表4.5所示。Lineltem表中的外键约束:dishNum属性参照dish表的主键(num),orderNum属性参照order表的主键(num)。
表 4.5订单项(明细)表

(7)orders表主要是记录了订单的基本信息。表结构设计如表4.6所示。ordes表中的外键约束:customer属性参照customer表的主键(num)。
表 4.6订单表

(7)comment表主要是记录了顾客评价的基本信息。表结构设计如表4.7所示。ordes表中的外键约束:customer属性参照customer表的主键(num),orderNum属性参照order表的主键(num)。
表 4.7评价表

视图设计
(1)dishInfo视图主要是记录了菜品的基本信息。由于dish表中存储的是分类编号,看起来很不方便,于是分类名称添加到视图中,视图的定义如表4.8所示。
表4.8 dishInfo视图定义
SELECT
dish.num AS num,
category.name AS cName,
dish.name AS dName,
dish.price AS price,
dish.picture AS picture,
dish.description AS description
FROM
( category JOIN dish )
WHERE
( category.num = dish.categoryNum )
(2)lineitemInfo视图主要是记录了顾客可见的订单项基本信,记录了基本的菜品信息和订单信息,视图定义如表4.9所示。
表4.9 lineitemInfo视图定义
SELECT
lineitem.orderNum AS orderNum,
dish.name AS dName,
dish.num AS dNum,
dish.picture AS picture,
dish.price AS price,
lineitem.quantity AS quantity,
lineitem.amount AS amount
FROM
( lineitem JOIN dish )
WHERE
( lineitem.dishNum = dish.num )
4.2类的设计
LoginRegisterController
customerService:CustomerService
merchantService:MerchantService
+sendSMS(tel:String):String
+login(account:String,pwd:String,identity: String):String
+telLogin(tel:String,verifyCode:String,identity:String):String
+register(tel:String,verifyCode:String,username:String,password:String,rePwd:String):String
图4.9 LoginRegisterController类图
(1)sendSMS函数,调用工具类,实现发送验证码的功能。
(2)telLogin函数,提供手机-验证码登录。
(3)register函数,顾客注册功能。
CustomerController
categoryService:CategoryService
dishService:DishService
commentService:CommentService
orderService:OrderService
lineitemService:LineitemService
+addDishitem(quantity:String,num:String,name:String, price: String, picture:String):String
+deleteDishitem(index:String):String
+payPage(remark:String):String
+confirmTrade(orderNum:String):String
+cancelTrade(orderNum:String):String
+applyRefund(orderNum:String):String
-query(out_trade_no:String):String
-upload(file:MultipartFile,fileName:String):String
+addComment(file:MultipartFile,orderNum:String, number:String,content:String):String
图4.10 CustomerController类图
(1)addDishitem函数:顾客加餐。
(2)deleteDishitem函数:在顾客准备下单时,选择性的删除商品。
(3)payPage函数:支付宝沙箱环境支付。
(4)confirmTrade函数:顾客确认收获,交易完成。
(5)cancelTrade函数:顾客未付款,取消订单。
(6)applyRefund函数:顾客申请退款,由商家进行处理。
(7)query函数:支付交易查询。
(8)upload函数:上传评价时的配图。
(9)addComment函数:顾客在确认收货后,进行订单的评价。
MerchantController
categoryService:CategoryService
dishService:DishService
orderService:OrderService
merchantService:MerchantService
+modifyPass(mpass:String mpass, newpass:String):String
+pageShow(previous:String,next:String,all:String,nextPage:String ):String
+dishManagePage():String
+uploadDishPicture(file:MultipartFile):String
-upload(file:MultipartFile, filePath:String):String
+addDishDetail(categoryNum: String, name:String):String
+selectOrder(begin:String,end:String):String
-refund(orderNum:String, amount:String):String
图4.11 MerchantController类图
(1)modifyPass函数:商家修改密码。
(2)pageShow函数:菜品分页显示。
(3)dishManagePage函数:显示所有菜品。
(4)uploadDishPicture函数:商家添加菜品时,上传的菜品图片。
(5)upload函数:实现上传功能。
(6)addDishDetail函数:商家添加商品时,填写的菜品信息。
(7)selectOrder函数:根据时间段查询订单。
(8)refund函数:商家对订单进行退款。

图4.12 CategoryService类图

图4.13 CategoryDAOByMybatis类图
CategoryService类主要是调用CategoryDAOByMybatis类,实现具体功能。
(1)findAllCategories函数:查询所有的分类信息。
(2)findAllCategoryNames函数:查询所有的分类名称。

图4.14 CommentService类图

图4.15 CommentDAOByMybatis类图
CommentService类主要是调用CommentDAOByMybatis类实现功能。
(1)findAllComments方法是从数据库中查询所有的评价信息。
(2)findAllLabels方法查询的是与评价相关的所有标签。
(3)updateLabelByName方法当顾客评价时,更新选择的标签。
(4)addComment实现插入一条评论记录。
(5)updatePictureByNum方法是顾客评价时,附加配图,评价的文字信息和图片上传是分开处理的,所以需要在插入评论后再设置图片。
(6)selectAverageGrade方法用于查询平均评分,在店铺评价页面显示。

图4.16 DishService类图

图4.17 DishDAOByMybatis类图
DishService类主要调用DishDAOByMybatis类实现功能:
(1)findByCategoryNum函数实现根据分类编号查询商品。
(2)findAllDishInfo函数实现查询所有菜品信息。
(3)findDishByNum函数:根据菜品编号查询菜品的详细信息。
(4)addDish函数:插入一条菜品记录。
(5)deleteDish函数:删除一条菜品记录。
(6)selectDishInfoByKeyword函数:根据关键字查询菜品信息。

图4.18 LineitemService类图

图4.19 LineitemDAOByMybatis类图
LineitemService类主要调用LineitemDAOByMybatis类实现功能:
(1)addLineitem函数:插入一条订单项。
(2)selectByOrderNum函数:根据订单编号,查询此订单所有的订单项。

图4.20 OrderService类图

图4.21 OrderDAOByMybaits类图
OrderService类调用OrderDAOByMybaits类中的函数实现功能:
(1)addOrder函数:插入一条订单记录。
(2)findByCustomer函数:根据顾客账户,查询该顾客的所有订单。
(3)deleteByNum函数:根据订单编号,删除一个订单。
(4)findAllOrder函数:查询所有的订单信息。
(5)findBetweenAnd函数:根据时间段查询订单。
(6)updateStatusByNum函数:根据订单编号更新订单状态。如:从“支付成功”变为“交易成功”。
4.3具体功能实现
4.3.1按类别浏览菜品
顾客进入系统后,可以选择类别来查看对应的商品。界面图如4.22所示。

图4.22 浏览菜品
Controller层
/**

  • 根据菜品分类编号,显示某一类菜品
  • @param request 请求
  • @param categoryNum 分类编号
  • @return 分类编号对应的菜品页面
    /
    @RequestMapping("/dish")
    public String dish(HttpServletRequest request, String categoryNum) {
    request.setAttribute(“dishes”, dishService.findByCategoryNum(categoryNum));
    return “/customers/dish”;
    }
    Service层
    /
    *
  • 根据商品编号查询商品.
  • @param categoryNum 分类编号
  • @return 商品
    /
    public List findByCategoryNum(String categoryNum) {
    return dishDAOByMybatis.findByCategoryNum(categoryNum);
    }
    DAO层
    /
    *
  • 根据分类编号查询商品.
  • @param categoryNum 分类编号
  • @return 某个分类的所有商品
    */
    @Select(“select * from dish where categoryNum=#{categoryNum}”)
    List findByCategoryNum(@Param(“categoryNum”) String categoryNum);
    4.3.2查看历史订单
    顾客成功登录后,可以在导航栏处点击我的订单来查看自己的所有订单,我的订单页面上按时间降序显示了订单的简略信息,可以点击详情查看订单详情。

图4.23 浏览订单

图4.24 浏览订单详情
Controller层
/**

  • 顾客查看自己所有的订单
  • @return jsp页面
    /
    @RequestMapping("/ordersPage")
    public String ordersPage(HttpServletRequest request) {
    request.setAttribute(“orders”, orderService.findByCustomer(getCustomerNum(request)));
    return “/customers/orders”;
    }
    Service层
    /
    *
  • 根据顾客编号查询订单
  • @param customer 顾客编号
  • @return 顾客的所有订单
    /
    public List findByCustomer(int customer){
    return orderDAOByMybatis.findByCustomer(customer);
    }
    DAO层
    /
    *
  • 根据顾客编号查询订单
  • @param customer 顾客编号
  • @return 顾客的所有订单
    */
    @Select(“select * from orders where customer=#{customer} order by birth desc”)
    List findByCustomer(@Param(“customer”) int customer);
    4.3.3购物篮
    顾客成功登录后,可以点击查看自己的购物信息,购物篮页面显示了用户添加到购物篮的所有菜品以及数量,顾客可以删除菜品品、给商家留言,之后用户可以结账提交订单。页面如图4.25所示:

图4.25 购物篮详情
Controller层
/**

  • 显示订单项的页面
    */
    @RequestMapping(value = “/lineitems”)
    public String lineitems() {
    return “/customers/lineitems”;
    }
    4.3.4订单评价

图4.26 添加订单评价

图4.27 店铺评价页面
Controller层
/**

  • 用户确认收货后,对一个订单进行评价
  • @param request 请求
  • @param orderNum 订单号
  • @param number 评价等级
  • @param content 评价内容
  • @param choose 是否配图;当取值为’yes’时,代表选择了配图;当取值为’no’时,说明顾客没有选择配图
  • @param file 选择的文件
  • @return 评价完成后, 返回店铺所有评价页面
    /
    @RequestMapping("/addComment")
    public String addComment(HttpServletRequest request, MultipartFile file, String orderNum, String number, String content, String choose) throws IOException {
    /获取checkbox所有的选中值/
    String[] label = request.getParameterValues(“label”);
    for (String name : label) {
    /在数据库中跟新标签出现的次数
    /
    commentService.updateLabelByName(name);
    }
    /插入一条评论,并返回评论的编号/
    int commentNum = commentService.addComment(orderNum, getCustomerNum(request)
    , Integer.parseInt(number), content);
    if (“yes”.equals(choose)) {
    /上传的文件名/
    String uploadFileName = file.getOriginalFilename();
    /文件后缀/
    String suffix = uploadFileName.substring(uploadFileName.lastIndexOf("."));
    /对上传的图片进行重命名/
    String fileName = String.valueOf(commentNum).concat(suffix);
    /上传图片/
    upload(file, request, fileName);
    /更新数据库中评论的文件名/
    commentService.updatePictureByNum(commentNum, fileName);
    }
    return “redirect:/customer/commentsPage”;
    }
    Service层
    /**
  • 插入一条评价
  • @param orderNum 订单编号
  • @param customerNum 顾客编号
  • @param grade 评价等级
  • @param content 评价内容
  • @return 评价编号
    /
    public int addComment(String orderNum, int customerNum, int grade, String content) {
    Comment comment = new Comment();
    comment.setCustomerNum(customerNum);
    comment.setGrade(grade);
    comment.setContent(content);
    comment.setOrderNum(orderNum);
    commentDAOByMybatis.addComment(comment);
    return comment.getNum();
    }
    DAO层
    /
    *
  • 添加一条评价
  • @param comment 待添加的评价
  • @return 评价的编号
    */
    @CacheEvict(value = “comments”, allEntries = true)
    @Insert(“INSERT INTO comments(customerNum,orderNum,grade,content) VALUES” + " (#{customerNum}, #{orderNum},#{grade},#{content})")
    @Options(useGeneratedKeys = true, keyProperty = “num”, keyColumn = “num”)
    int addComment(Comment comment);
    4.3.5菜品管理
    商家在登录成功后,在菜品管理页面,可以查看、检索、编辑和删除菜品信息,页面如图4.28所示。

图4.28 菜品管理页面
在添加菜品页面,商家可以填写菜品信息,新增一个菜品,如图4.29所示。

图4.29 添加菜品页面
Controller层
/**

  • 显示所有菜品的页面
  • @param request 请求
  • @return jsp页面
    /
    @RequestMapping("/dishManagePage")
    public String dishManagePage(HttpServletRequest request) {
    List dishInfos = dishService.findAllDishInfo();
    if (request.getAttribute(“dishInfo”) == null) {
    request.setAttribute(“dishInfo”, dishInfos);
    }
    HttpSession session = request.getSession();
    session.setAttribute(“begin”, 0);
    session.setAttribute(“end”, dishInfos.size() > 5 ? 4 : dishInfos.size() - 1);
    return “/merchants/allDish”;
    }
    Service层
    /
    *
  • 视图中查询所有菜品信息
  • @return 所有的菜品信息
    /
    public List findAllDishInfo() {
    return dishDAOByMybatis.findAllDishInfo();
    }
    DAO层
    /
    *
  • 从视图中查询所有的菜品信息
  • @return 菜品信息
    */
    @Select(“select * from dishinfo”)
    @Cacheable(“dishinfos”)
    List findAllDishInfo();
    4.3.6订单管理
    商家在登录成功后,在订单管理页面,可以查看所有订单,也可以按时间段查看订单信息,在订单页面也可以处理退款,如图4.30所示。

图4.30 订单管理页面
Controller层
/**

  • 退款
  • @param request 请求
  • @return 是否退款成功
  • @throws AlipayApiException 退款异常
    /
    @RequestMapping("/refund")
    public String refund(HttpServletRequest request, String orderNum, String amount) throws AlipayApiException {
    //获得初始化的AlipayClient
    AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, “json”, AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
    //设置请求参数
    AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
    //商户订单号,商户网站订单系统中唯一订单号
    String out_trade_no = orderNum;
    //需要退款的金额,该金额不能大于订单金额,必填
    String refund_amount = amount;
    AlipayTradeRefundResponse response = alipayClient.execute(alipayRequest);
    outPut(response.getBody());
    if (response.isSuccess()) {
    /在数据库中更新订单状态/
    orderService.updateStatusByNum(orderNum, Order.TRADE_STATUS.get(Order.CLOSED));
    request.setAttribute(“success”, “退款成功”);
    }
    return “forward:/merchant/allOrder”;
    }
    Service层
    /
    *
  • 根据订单编号,更新订单状态
  • @param orderNum 订单编号
  • @param status 订单状态
    /
    public void updateStatusByNum(String orderNum, String status) {
    orderDAOByMybatis.updateStatusByNum(orderNum,status);
    }
    DAO层
    /
    *
  • 根据订单编号,更新订单状态
  • @param num 订单编号
  • @param status 订单状态
    */
    @CacheEvict(value = “orders”, allEntries = true)
    @Update(“update orders set status=#{status} where num=#{num}”)
    int updateStatusByNum(@Param(“num”) String num, @Param(“status”) String status);

5 系统测试
5.1功能测试
测试工具:selenium。开启录制后,在页面进行点击操作。通过回放的方式多次运行程序,还可以进行代码的调试。

图 5.1 测试工具
5.1.1 登录模块测试
根据登录模块,设计如表5.1所示的测试用例。在登录模块中,所设计的测试用例经测试,均通过。
表 5.1 登录模块测试用例
输入参数 预期输出 实际输出 是否通过
用户名:null
密码:null
验证码:null 弹出错误提示,验证码错误 登录失败,请用户重新输入 是
用户名:null
密码:null 弹出错误提示,用户名错误 登录失败,提示用户重新输入 是
用户名:201716040128
密码:null 弹出错误提示,密码错误 登录失败,提示用户重新输入 是
用户名:201716040128
密码:123456 弹出错误提示,密码错误 登录失败,提示用户重新输入 是
用户名:201716040128
密码:040128 登录成功,进入个人主页 登录成功,进入系统 是
5.1.2 点餐模块测试
根据点餐模块,设计如表5.2所示的测试用例。在点餐模块中,当用户手工输入非数字时,没有任何提示,如表5.3所示需要修改JavaScript代码,修改后测试用例通过,如图5.1所示。
表 5.2 点餐模块测试用例
输入参数 预期输出 实际输出 是否通过
点击加号按钮、点击减号按钮 订购数量数量加1、减一 订购数量数量加1、减一 是
输入数量为非数字 提示用户无法订餐 没有任何提示 否
输入数字5 提示用户加餐成功 提示用户加餐成功 是
输入数字12 提示用户最多只能加餐9份 提示用户加餐姿势不对 是
表 5.3 修改点餐模块错误
if(isNaN(count))//输入非数字
con = ‘小主加餐姿势不对哦
请重新输入’
layer.msg(con, {
time: 1500, //1.5s后自动关闭
btn: [‘明白了’, ‘知道了’, ‘哦’]
});

图5.2 提示用户加餐姿势不对
5.1.3 订单提交模块测试
根据订单提交模块,设计如表5.4所示的测试用例。在点餐模块中,当选择提交后时,出现了异常情况,如表5.5所示需要修改JavaScript代码。
表 5.4 订单提交模块的测试用例
测试用例 预期结果 实际结果 是否通过
删除订单项,选择确认删除 订单项从当前订单中移除 订单项从当前订单中移除 是
将订单项全部删除 显示没有可以结算的页面 显示顾客还没有订购任何东西 是
顾客留言为空 插入默认的留言信息 插入了默认的留言信息 是
点击提交按钮 转到支付页面 出现空指针异常 否
由于在支付页面的时候,订单编号是自动生成的,顾客无法进行改变,于是将input标签的disabled=“disabled”,当提交form的时候,却无法接收到参数,改成readonly即可。
表 5.5 修改订单提交模块错误
document.getElementById(“WIDout_trade_no”).setAttribute(“readonly”,true)
5.1.4 菜品管理模块测试
根据菜品管理模块,设计如表5.6所示的测试用例。在菜品管理模块中,当没有选择上传文件点击时出现了异常情况,如表5.7所示修改代码,修改后测试用例通过。
表 5.6 菜品管理模块的测试用例
输入参数 预期输出 实际输出 是否通过
上传文件为null 不进行用户响应 严重异常 否
选择上传文件龙猫.gif 显示上传成功 上传成功 是
填写价格为abc 提示管理员价格不合法 提示错误消息 否
填写价格为-2 提示管理员价格不合法 提示错误消息 是
填写价格为32 提示管理员添加成功 提示管理员添加成功 是
将菜品名称或者菜品描述设置为空 提示管理员此项是必填项 提示管理员菜品名称不能为空 是
菜品名称大于10个字符或者菜品描述大于255个字符 提示管理员信息输入过长,无法保存 提示管理员信息输入的太多 是

表 5.7 修改菜品管理模块上传文件为空错误
// 解析请求的内容提取文件数据
List formItems = upload.parseRequest(new ServletRequestContext(request));
if (formItems != null && formItems.size() > 0) {

表 5.8 改正添加菜品时价格判断模块
function inputCheck() {
const price = document.getElementById(“price”).value;
if (isNaN(price) || price < 0) {
alert(“菜品价格不合法”);
return false;
}
else
return true;
}
5.1.5 订单管理模块测试
根据订单管理模块,设计如表5.9所示的测试用例。在订单查询模块中,当时间起点大于时间终点时,是逻辑错误,但是预期结果和实际结果不符,如表5.10所示,修改JavaScript代码,修改后测试用例通过,如图5.3所示。
表 5.9 订单管理模块的测试用例
输入参数 预期输出 实际输出 是否通过
点击数据右侧的删除按钮 删除选择的订单 删除该行订单 是
输入时间起点为空 提示用户此项为必填项 提示用户错误 是
输入时间终点为空 提示用户此项为必填项 提示用户错误 是
时间起点大于时间终点 提示用户时间起点需要小于时间终点 没有任何提示,无订单的查询结果 否
由于Javascript执行错误,在进行查询的时候,当起点大于终点时并不能提示相应的信息。
表 5.10 修改订单管理模块的错误
form.verify({
select : function(value) {
var begin = document.getElementById(‘date’).value;
var end = document.getElementById(‘date2’).value;
if(begin > end){
return ‘日期选择不合法,起点需要小于等于终点’;
} } });

图 5.3 改正后的错误提示
5.2 性能测试
性能是指系统能够满足吞吐量或时延要求程度的指标,用每秒执行事务的数量或单个事务耗费的时间来表示。系统中采用了redis做缓存来提高性能,使用了jmeter工具来进行了检测,测试过程如图5.4、5.5所示,结果如图5.6所示。

图5.4 线程组配置

图5.5 HTTP请求配置

图5.6 性能测试结果
不加redis缓存时,进行测试,结果如图5.6所示。

图5.7 不加redis缓存测试结果
结果图上的属性含义如下:
(1)#Samples:表示这次测试中一共发出了多少个请求。
(2)Average:平均响应时间—默认情况下是单个 Request 的平均响应时间。
(3)Min:最小响应时间。
(4)Maximum:最大响应时间。
(5)Throughput:吞吐量——默认情况下表示每秒完成的请求数。
在有缓存的情况下,系统平均响应时间更低,两者的最小相应时间相差不多,但还是有缓存时低,最大响应时间相差较大,也还是有缓存比较占优势,而吞吐量最为明显的表明了有缓存时性能得到了较大的提高。
6 总结
6.1问题和解决
(1)订单添加时出错。如图6.1所示,出现异常,原因是:表中int类型属性的类型为null,而类的属性int不能为null,出现无法进行赋值的问题,解决的办法是将类的属性int改为integer。

图 6.1 添加订单出错
(2)添加菜品时出错。由于商品描述中含有空格键,在执行时出现如图6.2所示的错误,解决的办法是在执行的时候,不再设置参数,而是直接将sql字符串“+”商品描述。

图 6.2 添加菜品出错
(3)input标签中,如果加上disabled属性,不能再提交表单。使用request.getParameter()无法获取到,得到的值总是null。

图 6.3 disabled属性问题
(4)MySQL中的关键字:order、name都是MySQL中的关键字,起初将基本表的名字设为order,在执行的时候mybatis总是抛出异常。控制台localhost的输出窗口,才发现不能将关键字做为表名。
6.2改进设想
(1)添加统计营收功能。以可视化的方式进行数据统计,显示最受欢迎的菜品。除此之外,可以根据营收推算进货量、计算利润。
(2)排队预约功能。菜品资源是有限的,排队预约可以解决资源冲突问题。
(3)优惠活动功能。每逢佳节或者店铺周年庆,可以发放一些优惠券,以便吸引顾客。
6.3心得体会
这次课设中,实现了两个新的功能:手机-验证码登录、支付宝沙箱环境支付。之前总以为会很难,其实有很多短信平台,只需要注册、审核、付费即可,官方给的demo本地就能直接运行,觉得自己还是比较low的。
实现的系统是非常粗糙的,经不起测试,最基本的输入限制都没有考虑好。也没有商业价值,没有考虑多用户、并发、分布式。想到当下餐饮行业的三大巨头,它们的背后是整个公司,自然很多事情考虑的很周到,自己实在是有很大的进步空间。
最近遇到很多“项目经验”的问题,十分苦恼:没有实习经历、课设不算项目经验、没有科研成果、没有团队。在这个即将毕业的阶段,心情出现两极化:过度放松、过度焦虑,不想碌碌无为,却又太过平凡。想到当初报考软件专业的时候,自己对计算机算得上是一窍不通,经过三年的积累,我依然很喜欢这个专业,也想一直在这个领域中学习、进步。

链接: https://pan.baidu.com/s/1ReGYoyy3R1yYIHsyU87E9A
提取码: 2mcd
内含实验报告

大哥大姐跑代码的时候,注册的时候,别忘了改手机号,默认是我的,我已经收到很多验证码了

课程设计-点餐系统_第1张图片

你可能感兴趣的:(没人看系列,数据库,java,课程设计)