瑞吉外卖项目学习笔记(二)后台系统的员工管理业务开发
一、完善登录功能
1.1 问题分析
1.2 代码实现
package com.itheima.reggie.filter;//这是一个过滤器类
//登录检查过滤器import com.alibaba.fastjson.JSON;
import com.itheima.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.AntPathMatcher;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 检查用户是否已经完成登录*/
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
@Slf4j
public class LoginCheckFilter implements Filter {//路径匹配器,支持通配符写法(专门用来路径比较的)public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();/*** 过滤的方法* @param servletRequest* @param servletResponse* @param filterChain* @throws IOException* @throws ServletException*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) servletRequest;HttpServletResponse response = (HttpServletResponse) servletResponse;/*** 1、获取本次请求的URI* 2、判断本次请求是否需要处理(是否需要检查用户已经登录了)【检查登录状态】* 3、如果不需要处理,则直接放行* 4、判断登录状态,如果已登录,则直接放行* 5、如果未登录则返回未登录结果*///1、获取本次请求的URIString requestURI = request.getRequestURI();//日志:拦截到的请求log.info("拦截到的请求:{}", requestURI);//2、判断本次请求是否需要处理(是否需要检查用户已经登录了)【检查登录状态】//定义一些不需要处理的请求路径(直接放行),只拦截针对Controller的请求String[] urls = new String[]{"/employee/login","/employee/logout","/backend/**","/front/**"};//判断是否需要处理boolean check = check(urls, requestURI);//3、如果不需要处理,则直接放行//check = true时不需要处理if (check) {log.info("本次请求{}不需要处理", requestURI);//放行filterChain.doFilter(request, response);return;}//4、判断登录状态,如果已登录,则直接放行if (request.getSession().getAttribute("employee") != null) {log.info("用户已登录,用户id为{}", request.getSession().getAttribute("employee"));//放行filterChain.doFilter(request, response);return;}log.info("用户未登录");//5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));return;}/*** 路径匹配,检查本次请求是否需要放行* @param urls* @param requestURI* @return*///封装方法public boolean check(String[] urls,String requestURI) {for (String url : urls) {boolean match = PATH_MATCHER.match(url, requestURI);if (match) {return true;}}//整个for循环都遍历完了都没有匹配上,就返回falsereturn false;}
}
1.3 功能测试
二、新增员工
2.1 需求分析
2.2 数据模型
2.3 代码开发
package com.itheima.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Employee;
import com.itheima.reggie.service.EmployeeService;
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.HttpServletRequest;
import java.time.LocalDateTime;@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {//自动装配@Autowiredprivate EmployeeService employeeService;/*** 员工登录* @param request* @param employee* @return*///前端发送的请求是 post 请求@PostMapping("/login")//接收json数据//requset对象可以getpublic R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){/*** 1、将页面提交的密码password进行md5的加密处理* 2、根据页面提交的用户名username查询数据库* 3、如果没有查询到则返回登录失败的结果* 4、密码比对,如果不一致则返回登录失败结果* 5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果* 6、登录成功,将员工id存入Session并返回登录成功结果*/// 1、将页面提交的密码password进行md5的加密处理//从employee中把password拿到String password = employee.getPassword();//调用工具类中的md5加密的方法password = DigestUtils.md5DigestAsHex(password.getBytes());//2、根据页面提交的用户名username查询数据库LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();//添加查询条件queryWrapper.eq(Employee::getUsername, employee.getUsername());//数据库已经对user_name做了唯一约束Employee emp = employeeService.getOne(queryWrapper);//3、如果没有查询到则返回登录失败的结果if(emp == null){return R.error("登录失败");}//4、密码比对,如果不一致则返回登录失败结果if(!password.equals(emp.getPassword())){//密码匹配不成功return R.error("登录失败");}//登录成功//5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果if (emp.getStatus() == 0){return R.error("账号已经被禁用");}//6、登录成功,将员工id存入Session并返回登录成功结果request.getSession().setAttribute("employee", emp.getId());//这是我们从数据库中查出来的对象return R.success(emp);}/*** 退出方法*//*** 员工退出* @param request* @return*/@PostMapping("/logout")public R<String> logout(HttpServletRequest request){//清理Session中保存的当前登录员工的idrequest.getSession().removeAttribute("employee");return R.success("退出成功");}/*** 新增员工* @param employee* @return*/@PostMappingpublic R<String> save(HttpServletRequest request,@RequestBody Employee employee){log.info("新增员工,员工信息:{}",employee.toString());//设置初始密码:123456,需要进行md5加密处理。getBytes():设置成getBytes()数组employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));//登录时间和更新时间employee.setCreateTime(LocalDateTime.now());employee.setUpdateTime(LocalDateTime.now());//获得当前登录用户的idLong empId = (Long) request.getSession().getAttribute("employee");employee.setCreateUser(empId);employee.setUpdateUser(empId);//保存对象employeeService.save(employee);//新增员工成功return R.success("新增员工成功");}
}
package com.itheima.reggie.common;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;import java.sql.SQLIntegrityConstraintViolationException;/*** 全局异常捕获处理* RestController.class, Controller.class:只有有这两个注解的类都会被我们这个类来处理*/
@ControllerAdvice(annotations = {RestController.class, Controller.class}) //通知
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {/*** 异常处理方法* @return*/@ExceptionHandler(SQLIntegrityConstraintViolationException.class)public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex) {log.error(ex.getMessage());//判断异常获取信息中是否有:Duplicate entry(重复条目)if(ex.getMessage().contains("Duplicate entry")){//根据空格进行分割,把异常信息存储到 split数组中String[] split = ex.getMessage().split(" ");//获取数组中已经用户名信息(唯一约束)String msg = split[2] + "已存在";//输出错误信息(账户已存在的信息)//return 把错误信息输出到页面上return R.error(msg);}//显示到页面的信息return R.error("未知错误");}
}
2.4 功能测试
2.5 总结
1、根据产品原型明确业务需求
2、重点分析数据的流转过程和数据格式
3、通过debug断点调试跟踪程序执行过程
三、员工信息分页查询
3.1 需求分析
在后台显示界面,一页显示出所有员工信息不利于查看。
解决方法:将员工信息进行分页展示
- 输入框:可以添加过滤条件,在添加过滤条件的同时进行分页处理
- 页码展示、可以跳转到相应的页码、也可直接点击相应的页码
3.2 代码开发
3.2.1 梳理程序执行流程
- 页面发送 ajax 请求,将分页查询参数(page、pageSize、name)提交到服务器
- 服务端 Controller 接收页面提交的数据并调用 Service 查询数据
- Service 调用 Mapper 操作数据库,查询分页数据
- Controller 将查询到的分页数据转成 JSON 响应给页面
- 页面接收到分页数据并通过 ElementUI 的 Table 组件展示到页面上
分页插件的使用:
MyBatisPlus 给我们提供了一个分页插件。
package com.itheima.reggie.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 配置MybatisPlus 的分页插件,配置类要加 @Configuration 注解*/
@Configuration
public class MyBatisPlusConfig {//拦截器@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());return mybatisPlusInterceptor;}
}
服务端 Controller 接收页面提交的数据并调用 Service 查询数据
//返回泛型Page,这个是MyBatisPlus 封装的类//方法中的形参指的是:前端页面传递给我们的值/*** 员工信息的分页查询* @param page* @param pageSize* @param name* @return*/@GetMapping("/page")public R<Page> page(int page, int pageSize, String name){log.info("page = {},pageSize = {},name = {}",page,pageSize,name);return null;}
分页查询设置
//返回泛型Page,这个是MyBatisPlus 封装的类//方法中的形参指的是:前端页面传递给我们的值/*** 员工信息的分页查询* @param page* @param pageSize* @param name* @return*/@GetMapping("/page")public R<Page> page(int page, int pageSize, String name){log.info("page = {},pageSize = {},name = {}",page,pageSize,name);//底层是基于MyBatisPlus提供的分页插件进行分页//1、构建分页构造器(分页条件:告诉MyBatisPlus我要查第几页,第几条)Page pageInfo = new Page(page, pageSize);//2、构造条件构造器(封装过滤分页条件)LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper();//添加过滤条件,like查询//判断name是否为null,然后再来添加条件queryWrapper.like(StringUtils.isNotEmpty(name),Employee::getName,name);//添加排序条件(就是相当于在SQL语句中加一个OrderBy)queryWrapper.orderByDesc(Employee::getUpdateTime);//3、执行查询employeeService.page(pageInfo,queryWrapper);return R.success(pageInfo);}
3.3 功能测试
四、启动 / 禁用员工账号
4.1 需求分析
- 只有管理员(admin 用户)可以对其他普通用户进行启用、禁用操作
- 普通用户登录系统后启用、禁用按钮不显示
- 账户禁用的员工不能登录系统
- 账户启用的员工可以正常登录
- 如果某个员工账户状态为正常,则按钮显示为 “禁用”
- 如果员工账户状态为已禁用,则按钮显示为 “启用”
4.2 代码开发
在开发代码之前,需要梳理一下整个程序的执行流程:
- 页面发送 ajax 请求,将参数(id、status)提交到服务端
- 服务端 Controller 接收页面提交的数据并调用 Service 更新数据
- Service 调用 Mapper 操作数据库
本质:是一个更新操作(Update),修改状态码
启用、禁用(或者是编辑)员工账号,本质上就是一个更新操作,也就是对 status 状态字段进行操作。
在 Controller 中创建 update 方法,此方法是一个通用的修改员工信息的方法。
4.3 功能测试
4.4 代码修复
五、编辑员工信息
5.1 需求分析
在员工管理列表页面点击编辑按钮,跳转到编辑页面,在编辑页面回显员工信息并进行修改,最后点击保存按钮完成编辑操作。
5.2 代码开发
在开发代码之前需要梳理一下操作过程喝对应的程序的执行流程:
- 点击编辑按钮时,页面跳转到 add.html ,并在 url 中携带参数【员工 id】
- 在 add.html 页面获取 url 中的参数【员工 id】
- 发送 ajax 请求,请求服务端,同时提交员工 id 参数
- 服务端接收请求,根据员工 id 查询员工信息,将员工信息以 json 形式响应给页面
- 页面接收服务端响应的 json 数据,通过 VUE 的数据绑定进行员工信息回显
- 点击保存按钮,发送 ajax 请求,将页面中的员工信息以 json 方式提交给服务端
- 服务端接收员工信息,并进行处理,完成后给页面响应
- 页面接收到服务端响应信息后进行相应处理
5.3 功能测试
相关文章:

瑞吉外卖项目学习笔记(二)后台系统的员工管理业务开发
一、完善登录功能 1.1 问题分析 1.2 代码实现 package com.itheima.reggie.filter;//这是一个过滤器类 //登录检查过滤器import com.alibaba.fastjson.JSON; import com.itheima.reggie.common.R; import lombok.extern.slf4j.Slf4j; import org.slf4j.Logger; import org.slf…...

Unity OutLine 模型外描边效果
效果展示: 下载链接...

CRLF注入漏洞
1.CRLF注入漏洞原理 Nginx会将 $uri进行解码,导致传入%0a%0d即可引入换行符,造成CRLF注入漏洞。 执行xss语句 2.漏洞扩展 CRLF 指的是回车符(CR,ASCII 13,\r,%0d) 和换行符(LF,ASCII 10,\n&am…...

理解接口回调及其在 RabbitMQ 中的实际运用
介绍 接口回调是一种常见的编程模式,它在异步编程中发挥着重要作用。本文将通过一个简单的示例介绍接口回调的概念和原理,并探讨它在 RabbitMQ 中的实际应用。 接口回调的概念 接口回调是一种编程模式,用于在异步编程中实现回调机制。它允许…...

大模型日报2024-05-31
大模型日报 2024-05-31 大模型资讯 Anthropic揭示Claude大语言模型的内部机制 摘要: 研究人员将大语言模型的活动模式与特定概念关联起来,并展示了他们可以通过调整这些模式来控制AI模型的行为。 Mistral AI开源新款代码语言模型Codestral 摘要: 人工智能初创公司Mi…...

HarmonyOS 鸿蒙DevEco:导入无法运行提示Sync failed
场景:导入官网下载的案例后导入发现无法运行模拟机,Notifications提示Sync failed... 解决:查看Cause发现是版本问题,通过修改相关内容来解决该问题 1、打开案例地址找到hvigor文件夹 2、打开hvigor-config.json5,将&…...

kafka的安装
windows下kafka的安装 【Kafka】Windows下安装Kafka(图文记录详细步骤)_windows安装kafka-CSDN博客 kafka生产消息 kafka消费消息...

代码随想录算法训练营第36期DAY45
DAY45 1两数之和 [https://www.bilibili.com/video/BV1pt421u7qG/?spm_id_from333.880.my_history.page.click&vd_sourcebaa5f3043be10f96febc0c68c5983df5] 出自B站热血编程系列,主要是复习双指针sum写法、重载比较运算符 class Solution {public: vec…...

springboot+vue 社区养老服务系统
Springbootvue社区居家养老服务系统,数据库mysql,mybatis框架,有可视化页面。 功能: 用户管理 养老服务管理 护理人员管理 服务类型管理 健康状况管理 社区管理 服务区管理 娱乐资讯管理 咨询分类管理 反馈建议 系统简历管理 轮播…...

AI 赋能前端 -- 文本内容概要生成
幸福不在于你获得了什么,而在于你比他人多获得了什么 是比较出来的 大家好,我是柒八九。一个专注于前端开发技术/Rust及AI应用知识分享的Coder 此篇文章所涉及到的技术有 OpenAILangChainRust/WebAssemblyWeb Workerreact+ts+vite配置环境变量(env)因为,行文字数所限,有些概…...

orin部署tensorrt、cuda、cudnn、pytorch、onnx
绝大部分参考https://blog.csdn.net/qq_41336087/article/details/129661850 非orin可以参考https://blog.csdn.net/JineD/article/details/131201121 报错显卡驱动安装535没法安装、原始是和l4t-cuda的部分文件冲突 Options marked [*] produce a lot of output - pipe it t…...

使用javacv对摄像头视频转码并实现播放
要实现Java接受RTSP流解码,并推送给前端实现播放实时流,可以使用一些流媒体处理库,比如JavaCV或者FFmpeg等。以下是一个简单的示例代码: 1.控制层方面的 根据视频rtsp流链接打开转换,通过响应写出流到前台使用flvjs播…...

Linux网络-Socket套接字_Windows与Linux端双平台基于Udp传输协议进行多线程跨平台的服务器与客户端网络通信的简易聊天室实现
文章目录 一、Socket套接字二、Udp 常见API1. int socket(int domain, int type, int protocol);2. int bind(int socket, const struct sockaddr *address, socklen_t address_len);struct sockaddr 3. ssize_t recvfrom(int socket, void *restrict buffer, size_t length, i…...

20分钟快速入门SQL
SQL(Structured Query Language,结构化查询语言)是一种专门用来管理和操作关系型数据库的编程语言。以下是SQL入门的一些基础概念和教程: 1. SQL基础 数据库(Database):存储数据的集合。表&am…...

汇总区间,合并区间
题目一: 代码如下: vector<string> summaryRanges(vector<int>& nums) {vector<string> ret;if (nums.size() 0)return ret;int n nums.size();int i 0;while (i < n){int prev i;i;while (i < n && nums[i] n…...

Web程序设计-实验05 DOM与BOM编程
题目 【实验主题】 影视网站后台影视记录管理页设计 【实验任务】 1、浏览并分析多个网站后台的列表页面、编辑页面(详见参考资源,建议自行搜索更多后台页面)的主要元素构成和版面设计,借鉴并构思预期效果。 2、新建 index.h…...

Window系统安装Docker
因为docker只适合在liunx系统上运行,如果在window上安装的话,就需要开启window的虚拟化,打开控制面板,点击程序,在程序和功能中可以看到启动和关闭window功能,点开后,找到Hyper-V,Wi…...

RabbitMQ不完整的笔记
同步的不足 1、拓展性差,当要添加功能时,需要在原来的功能代码上做修改,高耦合。 2、性能下降,调用者需要等待服务提供者执行完返回结果后,才能继续向下执行 3、级联失败,由于我们是基于OpenFeign调用交易…...

微软Edge浏览器深度解析:功能、同步、隐私与安全
微软Edge浏览器是微软公司开发的一款网页浏览器,它基于Chromium内核,提供了快速、安全和兼容性良好的网页浏览体验。以下是关于微软Edge浏览器的详细信息和使用指南: 微软Edge浏览器的主要特点: 1. 基于Chromium内核: 渲染引擎:Chromium内核是基于开源项目Blink的,它…...

网络性能测试工具:iperf3介绍
文章目录 前言一、iperf3 的安装和使用下载和安装参数说明 二、iperf3 测试服务端启动客户端启动服务端输出反向测试客户端服务端 前言 新接触的网络环境如何评估网络带宽和吞吐量呢,有的项目没有对业务流量进行合理规划,服务或者中间件出口带宽经常有被…...

scp:Linux系统本地与远程文件传输命令
scp 是Linux系统中用于在本地主机和远程主机之间进行文件传输的命令。 详细说明: scp 命令用于安全地将文件从一个主机传输到另一个主机,所有传输数据都是加密的。语法: scp [参数] [源文件路径] [目标主机:目标路径] 参数说明:…...

python基础(习题、资料)
免费提取资料: 练习、资料免费提取。持续更新迅雷云盘https://pan.xunlei.com/s/VNz6kH1EXQtK8j-wwwz_c0k8A1?pwdrj2x# 本文为Python的进阶知识合辑,包括列表(List)、元组(Tuple)、字典(Dic…...

shell脚本免交互
shell脚本的编写一方面为了减少我们命令的输入,另一方面也可以进行简单的自动化运行,其中为了实现自动化过程,一个很重要的点就是免交互,本篇文章跟大家简单分享两个常用的免交互的方法。 Here Document Here document 通过内联重…...

WPF学习笔记:给文字添加线性渐变效果
<TextBox Text"XXX信息管理系统" VerticalAlignment"Center" Background"Transparent" HorizontalAlignment"Center" FontSize"35" FontWeight"Normal"> <TextBox.Effect> <…...

Fully Convolutional Networks for Semantic Segmentation--论文笔记
论文笔记 资料 1.代码地址 2.论文地址 https://arxiv.org/abs/1411.4038 3.数据集地址 论文摘要的翻译 卷积网络是强大的视觉模型,可以产生特征层次结构。我们表明,卷积网络本身,经过端到端,像素对像素的训练,在…...

Camworks编程怎么样:深度解析其四大特点、五大应用领域、六大优势与七大挑战
Camworks编程怎么样:深度解析其四大特点、五大应用领域、六大优势与七大挑战 Camworks编程,作为计算机辅助制造(CAM)领域的一款重要软件,近年来在制造业中得到了广泛的应用。那么,Camworks编程究竟怎么样呢…...

【Linux】操作系统之冯诺依曼体系
🎉博主首页: 有趣的中国人 🎉专栏首页: Linux 🎉其它专栏: C初阶 | C进阶 | 初阶数据结构 小伙伴们大家好,本片文章将会讲解 操作系统中 冯诺依曼体系 的相关内容。 如果看到最后您觉得这篇文…...

c++ QT 实现QMediaPlayer播放音频显示音频级别指示器
文章目录 效果图概述代码总结 效果图 概述 QMediaPlayer就不介绍了,就提供了一个用于播放音频和视频的媒体播放器 QAudioProbe 它提供了一个探针,用于监控音频流。当音频流被捕获或播放时,QAudioProbe 可以接收到音频数据。这个类在需要访问…...

失之毫厘差之千里之load和loads
起源 最近在读pandas库的一些文档的时候,顺便也会将文档上的一些demo在编辑器中进行运行测试,其中在读到pandas处理Json数据这一节的时候,我还是像往常一样,将文档提供的demo写一遍,结果在运行的时候,直接…...

element ui在移动端的适配问题
element ui在移动端的适配问题 问题1: 给el-table表头添加背景色,使用以下代码 :header-row-style“{ background: ‘linear-gradient(90deg, #0079FA 0%, #00C7DD 100%)’ }” 在安卓手机上显示正常,在ios手机上显示背景色添加到每一个th中…...