瑞吉外卖项目学习笔记(二)后台系统的员工管理业务开发

news2025/1/18 14:03:28

一、完善登录功能

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
     */
    @Override
    public 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、获取本次请求的URI
        String 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循环都遍历完了都没有匹配上,就返回false
        return 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 {

    //自动装配
    @Autowired
    private EmployeeService employeeService;


    /**
     * 员工登录
     * @param request
     * @param employee
     * @return
     */
    //前端发送的请求是 post 请求
    @PostMapping("/login")
    //接收json数据
    //requset对象可以get
    public 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中保存的当前登录员工的id
        request.getSession().removeAttribute("employee");
        return R.success("退出成功");
    }

    /**
     * 新增员工
     * @param employee
     * @return
     */
    @PostMapping
    public 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());

        //获得当前登录用户的id
        Long 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 梳理程序执行流程

  1. 页面发送 ajax 请求,将分页查询参数(page、pageSize、name)提交到服务器
  2. 服务端 Controller 接收页面提交的数据并调用 Service 查询数据
  3. Service 调用 Mapper 操作数据库,查询分页数据
  4. Controller 将查询到的分页数据转成 JSON 响应给页面
  5. 页面接收到分页数据并通过 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 {
    
    //拦截器
    @Bean
    public 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 需求分析

  1. 只有管理员(admin 用户)可以对其他普通用户进行启用、禁用操作
  2. 普通用户登录系统后启用、禁用按钮不显示
  3. 账户禁用的员工不能登录系统
  4. 账户启用的员工可以正常登录
  5. 如果某个员工账户状态为正常,则按钮显示为 “禁用”
  6. 如果员工账户状态为已禁用,则按钮显示为 “启用”

4.2 代码开发

在开发代码之前,需要梳理一下整个程序的执行流程:

  1. 页面发送 ajax 请求,将参数(id、status)提交到服务端
  2. 服务端 Controller 接收页面提交的数据并调用 Service 更新数据
  3. Service 调用 Mapper 操作数据库

本质:是一个更新操作(Update),修改状态码

启用、禁用(或者是编辑)员工账号,本质上就是一个更新操作,也就是对 status 状态字段进行操作。

在 Controller 中创建 update 方法,此方法是一个通用的修改员工信息的方法。

4.3 功能测试

4.4 代码修复

五、编辑员工信息

5.1 需求分析

在员工管理列表页面点击编辑按钮,跳转到编辑页面,在编辑页面回显员工信息并进行修改,最后点击保存按钮完成编辑操作。

5.2 代码开发

在开发代码之前需要梳理一下操作过程喝对应的程序的执行流程:

  1. 点击编辑按钮时,页面跳转到 add.html ,并在 url 中携带参数【员工 id】
  2. 在 add.html 页面获取 url 中的参数【员工 id】
  3. 发送 ajax 请求,请求服务端,同时提交员工 id 参数
  4. 服务端接收请求,根据员工 id 查询员工信息,将员工信息以 json 形式响应给页面
  5. 页面接收服务端响应的 json 数据,通过 VUE 的数据绑定进行员工信息回显
  6. 点击保存按钮,发送 ajax 请求,将页面中的员工信息以 json 方式提交给服务端
  7. 服务端接收员工信息,并进行处理,完成后给页面响应
  8. 页面接收到服务端响应信息后进行相应处理

5.3 功能测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1719952.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LAMMPS - 分子动力学模拟器

本文翻译自&#xff1a;https://www.lammps.org/ 文章目录 一、关于 LAMMPS下载作者R&D 100 二、LAMMPS 亮点毛细血管中的血流 一、关于 LAMMPS 官网&#xff1a; https://www.lammps.org/ github &#xff1a;https://github.com/lammps/lammps LAMMPS 分子动力学模拟器…

智能制造案例专题|与MongoDB一起解锁工业4.0转型与增长的无限潜力!

MongoDB 智能制造 数字化技术的洪流在各个产业链的主干和枝节涌现。在工业制造领域&#xff0c;能否通过数字化技术实现各生产要素、生产环节之间的紧密配合&#xff0c;高效规划、管理整个生产流程&#xff0c;是企业提升韧性、赢得竞争的关键。随着工业4.0的深入发展和智能…

易语言推箱子游戏(附带源码)

易语言推箱子游戏 易语言易语言的安装易语言功能特色易语言安装步骤易语言常见问题 导入游戏源码部分源码领取源码下期更新预报 易语言 易语言&#xff08;EPL&#xff09;是一门以中文作为程序代码编程语言&#xff0c;其以“易”著称&#xff0c;创始人为吴涛。易语言早期版…

记 Codes 开源免费研发管理平台 —— 日报与工时融合集中式填报的创新实现

继上一回合生成式全局看板的创新实现后&#xff0c;本篇我们来讲一讲日报与工时融合集中式填报的创新实现。 市面上所有的研发管理软件&#xff0c;大多都有工时相关功能&#xff0c;但是却没有日报功能&#xff0c;好像也没什么问题&#xff0c;但是在使用过程中体验非常不…

【设计模式】JAVA Design Patterns——Facade(外观模式)

&#x1f50d;目的 为一个子系统中的一系列接口提供一个统一的接口。外观定义了一个更高级别的接口以便子系统更容易使用。 &#x1f50d;解释 真实世界例子 一个金矿是怎么工作的&#xff1f;“嗯&#xff0c;矿工下去然后挖金子&#xff01;”你说。这是你所相信的因为你在使…

先进的无人机GPS/GNSS模块解决方案

由于多星座支持和增强的信号接收能力&#xff0c;先进的GNSS模块提供了更高的精度和可靠性。集成传感器融合补偿信号中断&#xff0c;实现无缝导航。内置实时运动学(RTK)支持提供厘米级的定位精度。这些模块还优先考虑低功耗和紧凑的尺寸&#xff0c;确保更长的飞行时间和对无人…

第四范式Q1业务进展:驰而不息 用科技锻造不朽价值

5月28日&#xff0c;第四范式发布今年前三个月的核心业务进展&#xff0c;公司坚持科技创新&#xff0c;业务稳步拓展&#xff0c;用人工智能为千行万业贡献价值。 今年前三个月&#xff0c;公司总收入人民币8.3亿元&#xff0c;同比增长28.5%&#xff0c;毛利润人民币3.4亿元&…

Vue3项目练习详细步骤(第四部分:文章管理页面模块)

文章列表查询 页面主体结构 接口文档 接口调用 添加文章列表 添加组件 富文本编辑器 封面图片上传 接口文档 接口调用 编辑文章列表 结构调整 数据回显 接口文档 绑定请求数据 删除文章列表 接口文档 绑定请求数据 文章列表查询 页面主体结构 在ArticleManag…

太速科技-基于3U VPX 4核8线程I7 X86主板

基于3U VPX 4核8线程I7 X86主板 一、产品概述 该产品是一款基于第六代Intel i7四核八线程处理器的高性能3U VPX刀片式计算机。产品提供了4个x4 PCIe 3.0总线接口&#xff0c;其中2个x4 PCIe 3.0接口可配置为1个x8 PCIe3.0接口&#xff0c;另外2个x4 PCIe 3.0接口可灵活配置…

微信小程序教程DAY3

box标签 第二种方法 绿色第一种 第一种更好 效果一样 完成这个项目 先写循环

Git基本使用教程(学习记录)

参考文章链接&#xff1a; Git教程&#xff08;超详细&#xff0c;一文秒懂&#xff09; RUNOOB Git教程 Git学习记录 1Git概述 1.1版本控制软件功能 版本管理&#xff1a;更新或回退到历史上任何版本&#xff0c;数据备份共享代码&#xff1a;团队间共享代码&#xff0c;…

mirth Connect 自定义JAVA_HOME

mirth Connect 自定义JAVA_HOME 1、背景 服务器上安装了两个不同版本的Java&#xff0c;我希望Mirth服务使用与默认系统不同的版本。自定义指定java版本 2、解决方法 2.1 优先级说明 系统变量JAVA_HOME (设置后&#xff0c;mirth会根据这个进行启动运行服务&#xff0c;优先级…

2020 6.s081——Lab2:system calls

左岸的一座白色环形阶梯 浪人正在用和弦练习忧郁 晨曦下的少女听着吉他旋律 在许愿池边巴洛克式的叹息 ——许愿池的希腊少女 完整代码见&#xff1a;SnowLegend-star/6.s081 at syscall (github.com) System call tracing (moderate) 这个实验要求我们跟踪系统调用。 感觉实…

软件设计师,下午题 ——试题六

模型图 简单工厂模式 工厂方法模式抽象工厂模式生成器模式原型模式适配器模式桥接模式组合模式装饰&#xff08;器&#xff09;模式亨元模式命令模式观察者模式状态模式策略模式访问者模式中介者模式 简单工厂模式 工厂方法模式 抽象工厂模式 生成器模式 原型模式 适配器模式 桥…

nodemcu32s 和 mini D1 组局域网并用 webSocket 通信

实现思路 使用 mini D1 来搭建一个 webSocket 服务&#xff0c;然后使用 nodemcu32 连接&#xff0c;然后就可以进行通信了。 服务端代码&#xff08;mini D1&#xff09; 在代码中主要是需要控制好 loop 函数中的延时&#xff0c;也就是最后一行代码 delay&#xff0c;如果…

大模型时代的具身智能系列专题(六)

UCSD 王小龙组 王小龙是UCSD电子与计算机工程系的助理教授。他曾在加州大学伯克利分校与Alexei Efros和Trevor Darrell一起担任博士后研究员&#xff0c;在CMU RI获得了机器人学博士学位&#xff0c;师从Abhinav Gupta。他的研究重点是通过视频和物理机器人交互数据来学习3D和…

【AIGC】大型语言模型在人工智能规划领域模型生成中的探索

大型语言模型在人工智能规划领域模型生成中的新应用 一、引言二、LLM在规划领域模型生成中的潜力三、实证分析&#xff1a;LLM在规划领域模型生成中的表现四、代码实例&#xff1a;LLM在规划领域模型生成中的应用五、结论与展望 一、引言 随着人工智能技术的迅猛发展&#xff0…

yolov5-ros模型结合zed2相机部署在 Ubuntu系统

前言 本篇文章主要讲解yolov5-ros模型结合zed2相机进行实时检测&#xff0c;经改进实现了红绿灯检测&#xff0c;并输出检测类别与置信度&#xff01; 目录 一、环境配置二、zed2驱动安装三、yolov5-ros功能包配置四、运行官方权重文件四、运行自己权重文件 一、环境配置 1、…

分享6个打开就能让人眼前一亮的网站,每次浏览都像发现新大陆~

1、ZLibrary zh.zlibrary-be.se/ ZLibrary是一个广受欢迎的在线图书馆&#xff0c;它提供了一个庞大的电子书和文章资源库&#xff0c;数量超过千万。这个平台覆盖了国内外众多领域的电子书资源&#xff0c;几乎可以满足用户98%以上的搜索需求&#xff0c;无论是学术研究、文…

Netty中半包粘包的产生与处理:短连接、固定长度、固定分隔符、预设长度;redis、http协议举例;网络数据的发送和接收过程

目录 粘包、半包 相关概念 网络数据发送和接收过程 Netty半包粘包解决方案 ByteBuf获取和默认大小 短链接 固定长度 固定分隔符 预设长度 常见协议代码举例 redis协议 http协议 参考链接 粘包、半包 相关概念 程序处理过程中我们会通过缓冲区接收数据&#xff0c…