瑞吉外卖实战项目全攻略 | 您所在的位置:网站首页 › 黑马瑞吉外卖项目总结 › 瑞吉外卖实战项目全攻略 |
瑞吉外卖实战项目全攻略——第一天
该系列将记录一份完整的实战项目的完成过程,该篇属于第一天 案例来自B站黑马程序员Java项目实战《瑞吉外卖》,请结合课程资料阅读以下内容 该篇我们将完成以下内容: 软件开发整体介绍 瑞吉外卖项目介绍 开发环境搭建 后台登录系统功能开发 后台退出系统功能开发 软件开发整体介绍这个项目属于我的第一个完整项目,所以我们将从软件开发的概念来开始介绍 软件开发流程软件开发主要分为五个阶段,每个阶段带有不同的需求: 需求分析需求分析需要设计产品原型,产生需求规格说明书 设计设计主要负责产品文档,UI界面设计,概要设计,详细设计,数据库设计等设计信息 编码编码主要负责项目代码以及单元测试,也就是我们着重介绍的部分 测试测试主要负责准备测试用例,书写测试报告 上线运维上线运维主要包括软件环境安装,配置等 角色分工我们的公司中通常具有不同的岗位,这些岗位被称为角色 每个角色都具有不同的项目作用: 项目经理对整个项目负责,任务分配,把控进度 产品经理进行需求调研,输出需求调研文档,产品原型等 UI设计师根据产品原型输出界面效果图 架构师项目整体架构设计,技术选型等 开发工程师代码实现 测试工程师编写测试用例,输出测试报告 运维工程师软件环境搭建,项目上线 软件环境我们的项目软件在不同的情况下要处于不同的软件环境下 软件环境通常分为三种: 开发环境(development)开发人员在开发阶段使用的环境,一般外部用户无法访问 测试环境(test)专门给测试人员使用的环境,用于测试项目,一般外部用户无法访问 生产环境(production)即上线环境,正式提供对外服务的环境 瑞吉外卖项目介绍我们想要开发产品,就要对产品具有一定的了解 项目介绍首先我们介绍项目本身: 本项目(瑞吉外卖)是专门为餐饮企业(餐厅、饭店)定制的一款软件产 品,包括系统管理后台和移动端应用两部分。 其中系统管理后台主要提供给餐饮企业内部员工使用,可以对餐厅的菜品、套餐、订单等进行管理维护。 移动端应用主要提供给消费者使用,可以在线浏览菜品添加购物车、下单等。 再来介绍我们的开发计划: 本项目共分为3期进行开发 第一期主要实现基本需求,其中移动端应用通过H5实现,用户可以通过手机浏览器访问。 第二期主要针对移动端应用进行改进,使用微信小程序实现,用户使用起来更加方便。 第三期主要针对系统进行优化升级,提高系统的访问性能。 产品原型展示首先我们先来介绍产品原型: 产品原型就是一个产品成型前的简单框架,将页面的排版布局展现出来,使初步构思有一个可视化的展示 通过原型展示,可以更加直观的了解项目的需求和提供的功能注意点: 产品原型主要用于展示项目的功能,并不是最终的页面效果关于产品原型的展示我们不再展示,产品原型在资料中已全部提供~ 技术选型我们给出整个项目的技术栈展示:
我们同样给出整个项目需要实现的功能架构: 我们需要将项目中所出现的相关角色同列出来 本项目中大概出现三类角色: 后台系统管理员登录后台系统,拥有后台系统中的所有操作权限 后台系统普通员工登录后台系统,对菜品,套餐,订单进行管理 C端用户登录移动端应用,可以浏览菜品,添加购物车,设置地址,在线下单等 开发环境搭建在正式开始编程之前,我们需要将准备工作完成 我们需要从两方面进行环境搭建,我们的数据库使用MYSQL,开发工具采用IDEA 数据库环境搭建我们直接进入MYSQL数据库,这里使用MYSQL便捷工具Navicat: 创建数据库reggie到这里我们的数据库环境搭建就结束了 最后我们将导入数据库的表罗列出来进行一定说明展示: 我们的代码开发采用IDEA的Maven搭建: 创建maven(直接创建即可)我们在进行功能开发时一般分为三个步骤进行开发 需求分析首先我们需要得知,登录是在前端哪个页面通过什么方法请求数据 我们打开页面后,通过F12来查看点击相关功能后所进行的页面请求或者直接在后端查看请求 页面F12获取请求:(这里由于我这里已经完成功能,点击后直接跳转,无法获得数据) 后端查看请求: function loginApi(data) { return $axios({ 'url': '/employee/login', 'method': 'post', data }) }通过查询后我们可以发现点击登录后发送请求格式为下列: URL:http://localhost:8080/employee/login Request Method:POST因此我们需要书写Controller来完成该请求的相对应代码 另一方面,我们都知道我们前端和后端在交互时会通过一个固定的格式来返回请求 我们可以通过查询相关代码来确定返回格式: methods: { async handleLogin() { this.$refs.loginForm.validate(async (valid) => { if (valid) { this.loading = true let res = await loginApi(this.loginForm) if (String(res.code) === '1') { localStorage.setItem('userInfo',JSON.stringify(res.data)) window.location.href= '/backend/index.html' } else { this.$message.error(res.msg) this.loading = false } } }) } } // 我们可以发现res属性包含有code,data,msg等属性那么我们在后端代码中需要规定一个实体类来充当返回参数类 代码开发下面我们来到IDEA中书写我们前面所需要的内容: 构造实体类Employee // 我们创建entity文件夹专门书写实体类(资料中包含有实体类构造代码) // Employee是我们的员工表,相当于我们的账号和密码的主体类 package com.qiuluo.entity; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; import lombok.Data; import java.io.Serializable; import java.time.LocalDateTime; @Data public class Employee implements Serializable { private static final long serialVersionUID = 1L; private Long id; private String username; private String name; private String password; private String phone; private String sex; private String idNumber; private Integer status; private LocalDateTime createTime; private LocalDateTime updateTime; @TableField(fill = FieldFill.INSERT) private Long createUser; @TableField(fill = FieldFill.INSERT_UPDATE) private Long updateUser; } 构造数据层 package com.qiuluo.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.qiuluo.entity.Employee; import org.apache.ibatis.annotations.Mapper; // @Mapper帮助Spring自动识别数据层,采用全权代理开发 @Mapper // 继承BaseMapper,其中包括有许多基本数据库方法 public interface EmployeeMapper extends BaseMapper { } 构造业务层接口 package com.qiuluo.service; import com.baomidou.mybatisplus.extension.service.IService; import com.qiuluo.entity.Employee; // 继承IService实现多种方法 public interface EmployerService extends IService { } 构造业务层 package com.qiuluo.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.qiuluo.entity.Employee; import com.qiuluo.mapper.EmployeeMapper; import com.qiuluo.service.EmployerService; import org.springframework.stereotype.Service; // @Service帮助Spring自动识别 @Service // 继承ServiceImpl中的各种方法,第一个参数是Mapper,第二个参数是实体类 public class EmployeeServiceImpl extends ServiceImpl implements EmployerService { } 构造服务层 package com.qiuluo.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.qiuluo.common.R; import com.qiuluo.entity.Employee; import com.qiuluo.service.EmployerService; import com.qiuluo.service.impl.EmployeeServiceImpl; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; // 书写基本注解 // 日志注解 @Slf4j // REST形式的Controller @RestController // 设置整体映射地址 @RequestMapping("/employee") public class EmployeeController { // 自动装配employeeService @Autowired private EmployeeServiceImpl employeeService; } 构造返回结构类R // 我们构造一个返回结构类作为返回类型 package com.qiuluo.common; import lombok.Data; import java.util.HashMap; import java.util.Map; @Data public class R { private Integer code; //编码:1成功,0和其它数字为失败 private String msg; //错误信息 private T data; //数据 private Map map = new HashMap(); //动态数据 public static R success(T object) { R r = new R(); r.data = object; r.code = 1; return r; } public static R error(String msg) { R r = new R(); r.msg = msg; r.code = 0; return r; } public R add(String key, Object value) { this.map.put(key, value); return this; } } 逻辑分析前端需求并实现 package com.qiuluo.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.qiuluo.common.R; import com.qiuluo.entity.Employee; import com.qiuluo.service.EmployerService; import com.qiuluo.service.impl.EmployeeServiceImpl; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @Slf4j @RestController @RequestMapping("/employee") public class EmployeeController { @Autowired private EmployeeServiceImpl employeeService; /** * 员工登录 * */ @PostMapping("/login") public R login(HttpServletRequest request, @RequestBody Employee employee){ // 1. 将页面提交的密码经过md5加密(DigestUtils.md5DigestAsHex方法需要byte参数) String password = employee.getPassword(); password = DigestUtils.md5DigestAsHex(password.getBytes()); // 2.根据页面提交的用户名username查询数据库(采用LambdaQueryWrapper进行条件筛选) LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper(); lambdaQueryWrapper.eq(Employee::getUsername,employee.getUsername()); Employee emp = employeeService.getOne(lambdaQueryWrapper); // 3.如果没有查询到,判定失败 if (emp == null){ return R.error("登陆失败"); } // 4.密码比对,密码不一致失败 if (!emp.getPassword().equals(password)){ return R.error("登陆失败"); } // 5.查看员工状态 if (emp.getStatus() == 0){ return R.error("账户已禁用"); } // 6.登录成功,并将员工id存入Session并返回登录成功结果 request.getSession().setAttribute("employee",employee.getId()); return R.success(emp); } } 前端登录测试 # 测试时尽量将代码中书写的各种情况都测试一遍确保无误 后台退出功能开发我们在进行功能开发时一般分为三个步骤进行开发 需求分析员工登录成功后,页面跳转到系统首页页面(backend/index.html),此时显示当前用户名 当我们点击退出时,直接点击退出按钮即可退出页面,回到登录页面 同样我们采用F12或者后台请求查看: URL:http://localhost:8080/employee/logout Request Method:POST 代码开发我们回到EmployeeController程序中开发请求地址为employee/logout的POST请求即可 具体步骤包括有: 清理Session中的id 返回结果我们的实际开发步骤分为两步: 在EmployeeController中开发相对应的功能 package com.qiuluo.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.qiuluo.common.R; import com.qiuluo.entity.Employee; import com.qiuluo.service.EmployerService; import com.qiuluo.service.impl.EmployeeServiceImpl; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.DigestUtils; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @Slf4j @RestController @RequestMapping("/employee") public class EmployeeController { @Autowired private EmployeeServiceImpl employeeService; /** * 员工登录 * */ @PostMapping("/login") public R login(HttpServletRequest request, @RequestBody Employee employee){ // 1. 将页面提交的密码经过md5加密(DigestUtils.md5DigestAsHex方法需要byte参数) String password = employee.getPassword(); password = DigestUtils.md5DigestAsHex(password.getBytes()); // 2.根据页面提交的用户名username查询数据库(采用LambdaQueryWrapper进行比对) LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper(); lambdaQueryWrapper.eq(Employee::getUsername,employee.getUsername()); Employee emp = employeeService.getOne(lambdaQueryWrapper); // 3.如果没有查询到,判定失败 if (emp == null){ return R.error("登陆失败"); } // 4.密码比对,密码不一致失败 if (!emp.getPassword().equals(password)){ return R.error("登陆失败"); } // 5.查看员工状态 if (emp.getStatus() == 0){ return R.error("账户已禁用"); } // 6.登录成功,并将员工id存入Session并返回登录成功结果 request.getSession().setAttribute("employee",employee.getId()); return R.success(emp); } /** * 退出管理员 * */ @PostMapping("/logout") public R logout(HttpServletRequest request){ // 1. 将用户id从Session中删去 request.getSession().removeAttribute("employee"); // 2. 返回推出成功的信息即可 return R.success("退出成功"); } } 实际测试(点击退出键返回登录页面即可)在这里我们会点出该项目目前容易出错的位置,当然是对于我来说可能~ 设置静态资源映射易错点位置: 开发环境搭建中的Maven项目搭建易错原因: 书写过少,内容不够了解易错点: 设置静态映射属于配置类,需要添加@Configuration注解 该类本身不具有配置功能,需要继承WebMvcConfigurationSupport类实现其方法 设置静态类的方法为addResourceHandlers方法,采用内置参数registry的相关方法 registry的方法addResourceHandler后跟请求路径,addResourceLocations后跟映射的静态资源路径 // 正常情况下,我们的页面访问时会被Contoller拦截下来返回数据,这时我们就需要设置静态资源的转发路径 package com.qiuluo.config; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; // @Configuration设置为配置类,让Spring可以读取到该配置类 @Slf4j @Configuration // 注意:主要继承WebMvcConfigurationSupport成为配置类 public class WebMvcConfig extends WebMvcConfigurationSupport { // 设置静态资源的映射关系,继承方法addResourceHandlers即可 @Override protected void addResourceHandlers(ResourceHandlerRegistry registry) { // 日志输出 log.info("即将进行静态资源的映射:"); // 将请求路径 /backend/** 映射到 项目静态资源目录 resources/backend 下 // 特别注意:后面的路径需要加classpath: registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/"); registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/"); } } 结束语该篇内容到这里就结束了,希望能为你带来帮助~ 附录该文章属于学习内容,具体参考B站黑马程序员的Java项目实战《瑞吉外卖》 这里附上视频链接:业务开发Day1-01-本章内容介绍_哔哩哔哩_bilibili |
CopyRight 2018-2019 实验室设备网 版权所有 |