科技公司建设网站公司,那个网站做二手设备比较好,wordpress自定义分类调用,做网站需要填什么源码地址#xff1a;https://gitee.com/programmer-xiao-kai/reggie_tack_out 前置知识#xff1a;
Java基础知识Java Web vueSpring BootSSMMaven
软件开发流程 角色分工
项目经理:对整个项目负责#xff0c;任务分配、把控进度产品经理:进行需求调研#xff0c;输出需… 源码地址https://gitee.com/programmer-xiao-kai/reggie_tack_out 前置知识
Java基础知识Java Web vueSpring BootSSMMaven
软件开发流程 角色分工
项目经理:对整个项目负责任务分配、把控进度产品经理:进行需求调研输出需求调研文档、产品原型等UI设计师:根据产品原型输出界面效果图架构师:项目整体架构设计、技术选型等开发工程师:代码实现测试工程师:编写测试用例输出测试报告运维工程师:软件环境搭建、项目上线
项目简介
本项目瑞吉外卖是专门为餐饮企业(餐厅、饭店定制的一款软件产品包括系统管理后台和移动端应用两部分。其中系统管理后台主要提供给餐饮企业内部员工使用可以对餐厅的菜品、套餐、订单等进行管理维护。移动端应用主要提供给消费者使用可以在线浏览菜品、添加购物车、下单等。
技术选型 功能架构 角色
后台系统管理员登录后台管理系统拥有后台系统中的所有权限后台系统普通员工登录后台管理系统对菜品、套餐、订单等进行管理。
开发环境搭建
数据库环境搭建
数据库表 后台登录功能开发
开发步骤 创建一个实体类Employee和employee表进行映射 创建Controller,Service,Mapper 导入返回结果类R 此类是一个通用类R,服务端响应的所有结果最终都会包装成此种类型返回给前端页面 在Controller中创建登录方法
Slf4j
RestController
RequestMapping(/employee)
public class EmployeeController {Autowiredprivate EmployeeService employeeService;/*** 员工登录* param request* param employee* return*/PostMapping(/login)public REmployee login(HttpServletRequest request,RequestBody Employee employee){//1、将页面提交的密码password进行md5加密处理String password employee.getPassword();password DigestUtils.md5DigestAsHex(password.getBytes());//2、根据页面提交的用户名username查询数据库LambdaQueryWrapperEmployee queryWrapper new LambdaQueryWrapper();queryWrapper.eq(Employee::getUsername,employee.getUsername());Employee emp employeeService.getOne(queryWrapper);//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,emp.getId());return R.success(emp);}
}处理逻辑如下
将页面提交的密码password进行MD5加密处理根据页面提交的用户名username查询数据库如果没有查询到则返回登录失败结果密码比对如果不一致则返回登录失败结果查看员工状态如果为禁用状态则返回员工已经禁用结果登录成功将员工id存入Session并返回登录成功结果 后台退出功能开发
用户点击页面中退出按钮发送请求,请求地址为/employee/logout请求方式为POST
清理Session中的用户id;返回结果
/*** 员工退出* param request* return*/
PostMapping(/logout)
public RString logout(HttpServletRequest request){//清理Session中保存的当前登录员工的idrequest.getSession().removeAttribute(employee);return R.success(退出成功);
}员工管理后台开发
完善登录功能 方法使用过滤器或者拦截器中判断用户是否已经完成登录如果没有登录则跳转到登录页面 获取本次请求的URI判断本次请求是否需要处理如果不需要处理则直接放行判断登录状态如果一登录则直接放行如果未登录则返回结果直接放行如果未登录则返回未登录的结果
新增员工
需求分析数据模型代码开发
(1)、页面发送ajax请求将新增员工页面中输入的数据以json的数据形式提交到服务端
(2)、服务端Controller接收页面提交的数据并调用Service将数据进行保存
(3)、Service调用Mapper操作数据库保存数据
功能测试
/*** 新增员工* param employee* return*/
PostMapping
public RString save(HttpServletRequest request,RequestBody Employee employee){log.info(新增员工员工信息{},employee.toString());//设置初始密码123456需要进行md5加密处理employee.setPassword(DigestUtils.md5DigestAsHex(123456.getBytes()));//此部分抽取到common处//employee.setCreateTime(LocalDateTime.now());//employee.setUpdateTime(LocalDateTime.now());//获得当前登录用户的id//Long empId (Long) request.getSession().getAttribute(employee);//employee.setCreateUser(empId);//employee.setUpdateUser(empId);employeeService.save(employee);return R.success(新增员工成功);
}员工信息分页查询
需求分析代码开发 页面发送ajax请求,将分页查询参数(page,pageSize,name) 提交到服务端服务端Controller接收页面提交的数据并调用Service查询数据Service调用Mapper操作数据库查询分页数据Controller将查询到的分页数据响应给页面页面接收到分页数据并通过ElementUI的Table组件展示到页面上 功能测试
/*** 员工信息分页查询* param page* param pageSize* param name* return*/
GetMapping(/page)
public RPage page(int page,int pageSize,String name){log.info(page {},pageSize {},name {} ,page,pageSize,name);//构造分页构造器Page pageInfo new Page(page,pageSize);//构造条件构造器LambdaQueryWrapperEmployee queryWrapper new LambdaQueryWrapper();//添加过滤条件queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);//添加排序条件queryWrapper.orderByDesc(Employee::getUpdateTime);//执行查询employeeService.page(pageInfo,queryWrapper);return R.success(pageInfo);
}启动/禁用员工账号
需求分析 在员工管理列表页面可以对某个员工账号进行启用或者禁用操作。账号禁用的员工不能登录系统启用后的员工可以正常登录。 需要注意只有管理员(admin用户)才可以对其他普通用户进行启动、禁用等操作所以普通的用户登录系统后启动、禁用annual不显示。 代码开发 启用、禁用员工账号、本质上就是一个更新操作也就是对status状态字段进行操作在controller进行update的方法此方法就是一个通用的修改员工的办法。 页面发送ajax请求将参数(idstatus)提交给服务端服务端Controller接收页面提交的数据并调用Service更新数据Service调用Mapper操作数据库
功能测试
问题描述
通过观察控制台输出的SQL页面发现页面传递过来的员工id的值和数据库中的id值不一样由于分页查询时js对long型数据进行处理时丢失精度导致提交的id和数据库中的值不一致
解决办法:
我们可以在服务端给页面响应json数据时处理将long型数据统一转为字符串。
代码修复
修改员工信息
需求分析
在员工管理列表页面点击编辑按钮跳转到编辑页面在编辑页面回显员工信息并进行修改最后点击保存按钮。完成编辑操作
代码开发
点击编辑按钮时页面跳转到add.html并在url中携带参数[员工id]在add.html页面获取url中的参数[员工id]发送ajax请求请求服务端同时提交员工id参数服务端接收请求根据员工id查询员工信息将员工信息以json形式响应给页面页面接收服务端响应的json数据通过VUE的数据绑定进行员工信息回显点击保存按钮发送ajax请求将页面中的员工信息以json方式提交给服务端服务端接收员工信息并进行处理完成后给页面响应页面接收到服务端响应信息后进行相应处理
功能测试
/*** 根据id修改员工信息* param employee* return*/
PutMapping
public RString update(HttpServletRequest request,RequestBody Employee employee){log.info(employee.toString());long id Thread.currentThread().getId();log.info(线程id为{},id);//此部分抽取到common处//Long empId (Long)request.getSession().getAttribute(employee);//employee.setUpdateTime(LocalDateTime.now());//employee.setUpdateUser(empId);employeeService.updateById(employee);return R.success(员工信息修改成功);
}分类管理业务开发
公共字段自动填充
问题分析 对于新增员工时需要设置的创建时间创建人修改时间修改人等字段在编辑员工时需要设置修改时间和修改人等字段。 代码实现 MybatisPlus 公共字段自动填充也就是在插入或者更新的时候为指定的字段提供赋予指定的值,使用它的好处就是可以统一进行处理避免了重复的代码。 在实体类的属性上加入TableField注解指定自动填充的策略按照框架要求编写元数据对象处理器在此类中统一为公共字段赋值此类需要实现MetaObjectHandler接口
功能测试功能完善
还有一个小问题就是我们在自动填充createUser和updateUser时我们的UserID没有动态获取到Id的值故我们需要改造成动态获取当前用户的id
实现步骤
编写BaseContext工具类基于ThreadLocal封装的工具类在LoginCheckFilter的doFilter方法中调用BaseContext来设置当前登录用户的id在MymetaObjectHandler的方法中调用BaseContext获取用户的id
/*** 基于ThreadLocal封装工具类用户保存和获取当前登录用户id*/
public class BaseContext {private static ThreadLocalLong threadLocal new ThreadLocal();/*** 设置值* param id*/public static void setCurrentId(Long id){threadLocal.set(id);}/*** 获取值* return*/public static Long getCurrentId(){return threadLocal.get();}
}新增分类
需求分析管理分类信息分类包括两种类型分别是菜品分类和套餐分类。当我们在后台系统中添加菜品时需要选择一个菜品分类当我们在后台系统中添加一个套餐时需要选择一个套餐分类。 后台系统在可以 数据模型代码开发
实体类CategoryMapper接口CategoryMapper业务层接口CategoryService业务实现类CategoryServiceImpl控制层CategoryController
页面(backend/page/category/list.html)发送ajax请求将新增分类窗口输入的数据以json形式提交到服务端服务端Controller接收页面提交的数据并调用Service将数据进行保存 Service调用Mapper操作数据库保存数据
功能测试 Autowiredprivate CategoryService categoryService;/*** 新增分类* param category* return*/PostMappingpublic RString save(RequestBody Category category){log.info(category:{},category);categoryService.save(category);return R.success(新增分类成功);}分类信息分页查询 需求分析 代码开发
页面发送ajax请求将分页查询参数(page、pageSize)提交到服务端服务端Controller接收页面提交的数据并调用Service查询数据Service调用Mapper操作数据库查询分页数据Controller将查询到的分页数据响应给页面页面接收到分页数据并通过ElementUl的Table组件展示到页面上
功能测试
/*** 分页查询* param page* param pageSize* return*/GetMapping(/page)public RPage page(int page,int pageSize){//分页构造器PageCategory pageInfo new Page(page,pageSize);//条件构造器LambdaQueryWrapperCategory queryWrapper new LambdaQueryWrapper();//添加排序条件根据sort进行排序queryWrapper.orderByAsc(Category::getSort);//分页查询categoryService.page(pageInfo,queryWrapper);return R.success(pageInfo);}删除分类
需求分析代码开发
页面发送ajax请求将参数(id)提交到服务端服务端Controller接收页面提交的数据并调用Service删除数据Service调用Mapper操作数据库
功能测试
/*** 根据id删除分类* param id* return*/
DeleteMapping
public RString delete(Long id){log.info(删除分类id为{},id);//categoryService.removeById(id);categoryService.remove(id);return R.success(分类信息删除成功);
}功能完善 前面我们已经实现了根据id删除分类的功能但是并没有检查删除的分类是否关联了菜品或者套餐所以我们需要进行功能完善。 要完善分类删除功能需要先准备基础的类和接口: 1、实体类Dish和Setmeal 2、Mapper接口DishMapper和SetmealMapper 3、Service接口DishService和SetmealService 4、Service实现类DishServicelmpl和SetmealServicelmpl public interface SetmealService extends IServiceSetmeal {/*** 新增套餐同时需要保存套餐和菜品的关联关系* param setmealDto*/public void saveWithDish(SetmealDto setmealDto);/*** 删除套餐同时需要删除套餐和菜品的关联数据* param ids*/public void removeWithDish(ListLong ids);
}修改分类
在完成管理列表页面点击修改按钮弹出修改窗口回显分类信息并进行修改最后点击确定按钮完成修改操作。
文件上传下载
文件上传介绍
文件上传也称为upload是指将本地图片、视频、音频等文件上传到服务器上可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛我们经常发微博、发微信朋友圈都用到了文件上传功能。
文件上传时对页面的form表单由如下要求
method“post” 采用post方式提交数据enctype“multipart/form-data” 采用multipart格式上传文件type“file” 使用input的file控件上床
form methodpost action/common/upload enctypemultipart/form-datainput namemyFile typefile /input typesubmit value提交/
/form文件上传是的输入框 必须是post
文件下载也称为download是指将文件从服务器传输到本地计算机的过程。 通过浏览器进行文件下载通常有两种表现形式:
以附件形式下载弹出保存对话框将文件保存到指定磁盘目录直接在浏览器中打开
通过浏览器进行文件下载本质上就是服务端将文件以流的形式写回浏览器的过程。
文件的上传和下载代码实现
文件上传y
新增菜品
需求分析
数据模型
新增菜品其实就是将新增页面录入的菜品信息插入到dish表如果添加了口味做法还需要向dish_flavor表插入数据。所以在新增菜品时涉及到两个表:
代码开发
在开发业务之前先将需要用到的类和接口基本结构创建好
实体类DishFlavorMapper接口DishFlavorMapper业务层接口实现类业务层实现类DishFlavorServiceIMpl控制层DishController
代码完善
后台系统中可以管理菜品信息通过新增功能莱添茄一个新的菜品在添加菜品时需要选择当前菜品所属的菜品分类并且需要上传菜品图片在移动端会按照菜品分类来展示对应的菜品信息
在开发代码之前需要梳理一下新增菜品时前端页面和服务器的交互过程
页面backend/page/food/add.html发送ajax请求请求服务端获取菜品分类数据并显示到下拉框中 DTO,全称为Data Transfer Object,即数据传输对象一般用于展示层与服务层之间的数据传输。 菜品信息分页查询
需求分许
系统中的菜品数据很多的时候如果在一个页面中全部展示出来会显得比较乱不便于查看所以一般的系统中都会以分页的方式来展示列表数据。
代码开发
页面(backend/page/food/list/html)发送ajax请求将分页查询参数(page、pageSize,name)提交到服务端获取分页数据页面发送请求请求服务端进行图片下载用于页面图片展示 开发菜品信息分页查询功能其实就是在服务端编写代码去处理前端页面发送的这2次请求即可。 功能测试
修改菜品
需求分析
在菜品管理列表页面点击修改按钮跳转到修改菜品页面在修改页面回显菜品相关信息并进行修改,最后点击确定按钮完成修改操作
代码开发-梳理交互过程
页面发送ajax请求请求服务器获取分类数据用于菜品分类下拉框中数据显示页面发送ajax请求请求服务端根据id查询当前菜品信息用于菜品信息回显页面发送ajax请求请求服务端进行图片下载用于页面图片回显点击保存页面发送ajax请求将修改后的菜品相关信息数据以json的格式提交到服务端
功能测试
代码完善
套餐业务开发
新增套餐
需求分析
后台系统中可以管理套餐信息通过新增套餐功能来添加一个新的套餐在添加套餐时需要选择当前套餐所属的套餐分类和包含的菜品并且需要上传套餐对应的图片在移动端会按照套餐分类来展示对应的套餐。
数据模型
新增套餐其实就是将新增页面录入的套餐信息插入到setmeal表还需要向setmeal_dish表插入套餐和菜品关联数据。所以在新增套餐时涉及到两个表:
setmeal 套餐表setmeal_dish 套餐菜品关系表
代码开发
实体类SetmealDishDTO SetmealDtoMapper接口SetmealDishService业务层实现类 SetmealDishServiceImpl控制层SetmealController
代码开发——梳理交互过程
页面(backend/page/combo/add.html)发送ajax请求请求服务端获取套餐分类数据并展示到下拉框中页面发送ajax请求请求服务端获取菜品分类数据并展示到添加菜品窗口中页面发送ajax请求请求服务端根据菜品分类查询对应的菜品数据并展示到添加菜品窗口中页面发送请求进行图片上传请求服务端将图片保存到服务器页面发送请求进行图片下载将上传的图片进行回显点击保存按钮发送ajax请求将套餐相关数据以json形式提交到服务端
短信发送
短信服务介绍
这些第三方短信服务会和各个运营商(移动、联通、电信)对接我们只需要注册称为会员并且按照开发文档进行调用就可以发送信息
常用短信服务
阿里云短信服务介绍
验证码、短信通知、推广短信
腾讯云
京东梦网
乐信
代码开发
使用阿里云短信服务发送短信可以参考官方提供的文档即可
具体开发步骤
导入maven调用API
手机验证码登录
手机验证码登录方式方便快捷安全没有传统的用户名
数据模型
通过手机验证码登录时涉及到的为user表即用户表
代码开发-梳理交互过程
在登录之前(front/page/login.html)输入手机号点击【获取验证码】按钮页面发送ajax请求在服务端调用短信服务API给指定手机号发送验证码短信在页面登录输入验证码点击【登录】按钮发送ajax请求在服务端处理登录请求。
菜品展示购物车下单
导入用户地址薄相关功能代码
地址簿指的是移动端消费者用户的地址信息用户登录成功后可以维护自己的地址信息但是同一个用户只能有一个默认地址
数据模型
用户的地址信息会存储在address_book表中,即地址簿
菜品展示
代码开发——梳理交互过程
交互页面(front/index.html)发送ajax请求获取分类数据(菜品分类和套餐分类)页面发送ajax请求获取第一个分类下的菜品或者套餐
购物车功能模块开发
代码开发准备先将需要用到的类和接口基本结构创建好
实体类ShoppingCartMapper接口ShoppingCartMapper业务层接口ShoppingCartService业务层实现类ShoppingCartServiceImpl控制层ShoppingCartCont
导入maven调用API
手机验证码登录
手机验证码登录方式方便快捷安全没有传统的用户名
数据模型
通过手机验证码登录时涉及到的为user表即用户表
代码开发-梳理交互过程
在登录之前(front/page/login.html)输入手机号点击【获取验证码】按钮页面发送ajax请求在服务端调用短信服务API给指定手机号发送验证码短信在页面登录输入验证码点击【登录】按钮发送ajax请求在服务端处理登录请求。
菜品展示购物车下单
导入用户地址薄相关功能代码
地址簿指的是移动端消费者用户的地址信息用户登录成功后可以维护自己的地址信息但是同一个用户只能有一个默认地址
数据模型
用户的地址信息会存储在address_book表中,即地址簿
菜品展示
代码开发——梳理交互过程
交互页面(front/index.html)发送ajax请求获取分类数据(菜品分类和套餐分类)页面发送ajax请求获取第一个分类下的菜品或者套餐
购物车功能模块开发
代码开发准备先将需要用到的类和接口基本结构创建好
实体类ShoppingCartMapper接口ShoppingCartMapper业务层接口ShoppingCartService业务层实现类ShoppingCartServiceImpl控制层ShoppingCartCont