苍穹外卖项目笔记(3)——员工管理

前言

这些功能都没有展示对应的测试结果,可自行通过接口文档进行测试,也可以进行前后端联调测试,附代码链接:take-out

1新增员工

1.1 需求分析和设计

产品原型

接口设计

【注】code:操作成功返回1,否则返回0,可通过 msg 来设置失败的提示信息,一般表现为前端的弹窗。

数据库设计 

 

1.2 代码开发

根据新增员工接口设计对应的DTO

【拓展】DTO和实体类

DTO(Data Transfer Object):用于数据传输,只包含需要传输和展示的数据

实体类(Entity):用于持久化和业务逻辑的处理,包含数据库中所有字段以及对于的业务逻辑处理方法

 EmployeeController.java

    /**
     * 新增员工
     * @param employeeDTO
     * @return
     */
    //统一用 result 来封装返回结果
    //@RequestBody 表明接受的是 json 格式的数据
    @PostMapping
    @ApiOperation("新增员工")
    public Result save(@RequestBody EmployeeDTO employeeDTO) {
        log.info("新增员工:{}",employeeDTO);
        employeeService.save(employeeDTO);

        return Result.success();
    }

【拓展】

@GetMapping:将HTTP get 请求映射到特定处理程序的方法注解,

        是@RequestMapping(metho = RequestMethod.GET)的缩写

@PostMapping:将HTTP post 请求映射到特定处理程序的方法注解

        是@RequestMapping(metho = RequestMethod.POST)的缩写

 EmployeeMapper.java

    /**
     * 插入员工数据
     * @param employee
     */
    @Insert("insert into employ(name, username, password, phone, sex, id_number, create_time, update_time, create_user, update_user, status)" +
            "values" +
            "(#{name}, #{username}, #{password}, #{phone}, #{sex}, #{idNumber}, #{createTime}, #{updateTime},#{createUser},#{updateUser}, #{status})")
    void insert(Employee employee);

 EmployeeServiceImpl.java

    /**
     * 新增员工
     * @param employeeDTO
     */
    public void save(EmployeeDTO employeeDTO) {
        //传入的是DTO,为了方便封装前端提交的数据,但传给持久层,还是建议使用实体类,所以这里需要一个对象的转换,将DTO转换为我们的实体类
        Employee employee = new Employee();

        //由于DTO里的和Employee里面的属性名一样,所以可以通过对象的属性拷贝来赋值
        BeanUtils.copyProperties(employeeDTO, employee);

        //状态和初始密码都不希望直接锁死,所以通过常量的方式进行引用
        //设置账号的状态,默认正常状态 1表示正常 0表示锁定
        employee.setStatus(StatusConstant.ENABLE);

        //设置密码,默认密码123456(需要进行MD5码转换,还需要变为Byte数组)
        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));

        //设置当前记录的创建时间和修改时间
        employee.setCreateTime(LocalDateTime.now());
        employee.setUpdateTime(LocalDateTime.now());

        //设置当前记录的创建人和修改人
        //TODO 后期需要改为当前登录用户的ID
        employee.setCreateUser(10L);
        employee.setUpdateUser(10L);

        employeeMapper.insert(employee);

    }

1.3 代码完善

程序存在的问题:

  1. 录入的用户名已存在,抛出异常后没有处理
  2. 新增员工时,创建人 id 和修改人  id 设置为了固定值

针对第二个问题,需要通过某种方式(生成令牌)动态获取当前登录员工的 id: 

 解决:

① 员工登录成功后生成JWT令牌并响应给前端

EmployeeController.java:

        //登录成功后,生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.EMP_ID, employee.getId());
        String token = JwtUtil.createJWT(
                jwtProperties.getAdminSecretKey(),
                jwtProperties.getAdminTtl(),
                claims);

 ② 后续请求中,前端会携带JWT令牌,通过JWT令牌解析出当前员工登录id

JwtTokenAdminInterceptor.java:

        //1、从请求头中获取令牌
        String token = request.getHeader(jwtProperties.getAdminTokenName());

        //2、校验令牌
        try {
            log.info("jwt校验:{}", token); //log.info() 打印日志
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            //4、不通过,响应401状态码
            response.setStatus(401);
            return false;
        }

【注】通过上述两个步骤可以解析出登录员工的 id,如何将这个 id 传递给 Service 的 save 方法呢?需要借助 ThreadLocal ,它提供了一个存储空间,可以通过这个共享的空间实现消息传递!

在实际过程中,一般将 ThreadLocal 包装为一个工具类  :

package com.sky.context;

public class BaseContext {

    public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    public static void setCurrentId(Long id) {
        threadLocal.set(id);
    }

    public static Long getCurrentId() {
        return threadLocal.get();
    }

    public static void removeCurrentId() {
        threadLocal.remove();
    }

}

所以完善以后的整体代码如下: 

 EmployeeServiceImpl.java

        //设置当前记录的创建人和修改人
        employee.setCreateUser(BaseContext.getCurrentId());
        employee.setUpdateUser(BaseContext.getCurrentId());

 JwtTokenAdminInterceptor.java

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断当前拦截到的是Controller的方法还是其他资源
        if (!(handler instanceof HandlerMethod)) {
            //当前拦截到的不是动态方法,直接放行
            return true;
        }

        //1、从请求头中获取令牌
        String token = request.getHeader(jwtProperties.getAdminTokenName());

        //2、校验令牌
        try {
            log.info("jwt校验:{}", token);
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
            Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString());
            log.info("当前员工id:", empId);
            BaseContext.setCurrentId(empId);  // 把 id 存到线程的独立空间 ThreadLocal 里面去了
            //3、通过,放行
            return true;
        } catch (Exception ex) {
            //4、不通过,响应401状态码
            response.setStatus(401);
            return false;
        }
    }

1.2 员工分页查询

1.2.1 需求分析和设计

产品原型

接口设计

1.2.2 代码开发

 根据分页查询接口设计对应的 DTO

在我们后面所有的分页查询开发中,统一都封装成 PageResult 对象 :

员工信息分页查询后端返回的对象类型为:Result<PageResult> 

1.2.3 代码完善

存在问题:最后修改时间所对应的数据格式存在问题

解决方式:

方式一:在属性上加上注解,对日期进行格式化(只能处理单个实体)

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

方式二:在 WebMvcConfiguration 中扩展 Spring MVC 的消息转换器,统一对日期类型进行格式化处理

    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器...");
        //创建一个消息转换器对象
        MappingJackson2CborHttpMessageConverter converter = new MappingJackson2CborHttpMessageConverter();
        //为消息转换器设置一个对象转换器,对象转换器可以将Java 对象序列化为json数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转换器加入容器中,并排在第一位
        converters.add(0,converter);
    }

1.3 启用禁用员工账号

1.3.1 需求分析和设计

产品原型

业务规则

状态为启用,可操作为禁用;状态为禁用,可操作为启用。启用状态可登录系统,反之不可。

接口设计

1.3.2 代码开发

EmployeeServiceImpl.java

    /**
     * 启用禁用员工账号
     * @param status
     * @param id
     */
    @Override
    public void startOrstop(Integer status, Long id) {
        // update employee set status = ? where id = ?

//        //第一种写法
//        Employee employee = new Employee();
//        employee.setStatus(status);
//        employee.setId(id);

        //第二种写法,获得一个构建起对象,设置它的属性
        Employee employee = Employee.builder()
                .status(status)
                .id(id)
                .build();

        employeeMapper.update(employee);
    }

EmployeeController.java

    /**
     * 启用禁用员工账号
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}") //说明路径
    @ApiOperation("启用禁用员工账号")
    //对于查询类的,需要加上泛型;对于非查询类的就不需要了
    public Result startOrstop(@PathVariable Integer status,Long id) {
        log.info("启用禁用员工账号:{},{}",status,id);
        employeeService.startOrstop(status,id);
        return Result.success();
    }

1.4 编辑员工

1.4.1 需求分析和设计

产品原型

编辑员工功能涉及到的两个接口:

① 根据 id 查询员工信息

② 编辑员工信息

1.4.2 代码开发

EmployeeServiceImpl.java

    /**
     * 根据 id 查询员工
     * @param id
     * @return
     */
    @Override
    public Employee getById(Long id) {
        Employee employee = employeeMapper.getById(id);
        employee.setPassword("****");
        return null;
    }

    /**
     * 编辑员工信息
     * @param employeeDTO
     */
    @Override
    public void update(EmployeeDTO employeeDTO) {
        Employee employee = new Employee();
        BeanUtils.copyProperties(employeeDTO,employee); //属性拷贝

        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(BaseContext.getCurrentId());

        employeeMapper.update(employee);
    }

 EmployeeController.java

    /**
     * 根据 id 查询员工信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation("根据 id 查询员工信息")
    public Result<Employee> getById(@PathVariable Long id) {
        Employee employee = employeeService.getById(id);
        return Result.success(employee);
    }


    /**
     * 编辑员工信息
     * @param employeeDTO
     * @return
     */
    @PutMapping
    @ApiOperation("编辑员工信息")
    //@RequestBody:表明提交过来的是 json 数据
    public Result update(@RequestBody EmployeeDTO employeeDTO) {
        log.info("编辑员工信息:{}",employeeDTO);
        employeeService.update(employeeDTO);
        return Result.success();
    }

2 导入分类模块功能代码

2.1 需求分析和设计

产品原型

业务规则

  • 分类名称必须唯一
  • 分类按照类型可以分为菜品分类和套餐分类
  • 新添加的分类状态默认为“禁用”

数据库设计表(category)

2.2 代码导入

这部分实现方式和员工管理的内容相似,所以直接提供代码,将其分别导入对应包的下面即可

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Azure Machine Learning - Azure AI 搜索中的集成数据分块和嵌入

在基于索引器的索引编制中&#xff0c;Azure AI _集成矢量化_将数据分块和文本到矢量嵌入添加到技能中&#xff0c;它还为查询添加文本到矢量的转换。 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本…

我叫:选择排序【JAVA】

1.我是个啥子&#xff1f;&#xff1f; 选择式排序&#xff1a;属于内部排序法,从欲排序的数据中,按指定的规则选出某一元素&#xff0c;再依规定交换位置后达到排序的目的。 2.我的思想 基本思想:第一次从arr[0]~arr[n-1]中选取最小值&#xff0c;与arr[0]交换&#xff0c;第…

io多路复用:select、poll和epoll

1、为什么使用多路复用&#xff1a; 1.1单线程BIO监听socket 多路复用一般用于网络io当中&#xff0c;提到网络io我们肯定能想到socket。如果我们想要一个线程单纯的用向下文的方式监听很多个socket看他是否有事件发生&#xff0c;那这样是不可行。 但上一个socket1没有可读事…

哪个电脑录屏软件好用又免费?十大好用的免费录屏软件排行

屏幕录制软件是一个非常有用的辅助工具&#xff0c;可以帮助您录制屏幕上的所有内容&#xff0c;并根据需要将其转换为视频。 此外&#xff0c;免费的屏幕录像机可以为您节省大量不必要的费用。在这篇文章中&#xff0c;我将列出我在工作和学习中最有效使用的 10 个软件。 每…

OSG加载模型时显示读取进度

目录 1. 前言 2. 开发环境说明 3. 功能实现 3.1. 方法1 3.2. 方法2 3.3. 方法3 4. 附加说明 1. 前言 OSG中加载模型文件到视景器&#xff0c;一般通过osgDB::readXXXX系列开头的函数来加载模型&#xff0c;如&#xff1a;osgDB::readNodeFile、osgDB::readImageFile、os…

Pytest自动化测试框架:mark用法---测试用例分组执行

pytest中的mark&#xff1a; mark主要用于在测试用例/测试类中给用例打标记(只能使用已注册的标记名)&#xff0c;实现测试分组功能&#xff0c;并能和其它插件配合设置测试方法执行顺序等。 如下图&#xff0c;现在需要只执行红色部分的测试方法&#xff0c;其它方法不执行&am…

【精选】项目管理工具——Maven详解

Maven简介 Maven是一个项目管理工具。它可以帮助程序员构建工程&#xff0c;管理jar包&#xff0c;编译代码&#xff0c;完成测试&#xff0c;项目打包等等。 Maven工具是基于POM&#xff08;Project Object Model&#xff0c;项目对象模型&#xff09;实现的。在Maven的管理下…

【React】React 基础

1. 搭建环境 npx create-react-app react-basic-demo2. 基本使用 JSX 中使用 {} 识别 JavaScript 中的表达式&#xff0c;比如变量、函数调用、方法调用等。 if、switch、变量声明等属于语句&#xff0c;不是表达式。 列表渲染使用 map 。 事件绑定用&#xff1b;on 事件名称…

公寓水电管理系统

springbootmybatisthymeleaf 这次练习是尝试将layer与系统结合起来&#xff0c;将新增、修改、删除都和弹窗结合起来。 一、需求分析 二、数据库 三、模块 1、登录页面 哈哈哈&#xff0c;之前做的登录页面都好丑&#xff0c;这是目前做的最好看的一次了。 超级管理员&…

Java 教育局民办教育信息服务与监管平台

1) 项目背景 按照《中华人民共和国民办教育促进法》和《中华人民共和国政府信息公开条例》的相关规定&#xff0c;为满足学生和家长、社会各界获取权威信息的需求&#xff0c;着力解决服务老百姓最后一公里问题&#xff0c;达到宣传民办教育和引导家长择校的效果&#xff0…

Java实现图书管理系统

今天与大家分享的是一个图书管理系统&#xff0c;这里我们运用的是java基础的语法其中包括类和对象、继承、封装、多态、抽象类、接口还有数组等。 我们需要实现一个可以进行管理员操作和用户操作的图书管理系统&#xff0c;其中包括了管理员操作(查找&#xff0c;添加&#x…

SpringBoot中日志的使用log4j

SpringBoot中日志的使用log4j 项目中日志系统是必不可少的&#xff0c;目前比较流行的日志框架有 log4j、logback 等&#xff0c;这两个框架的作者是同一个 人&#xff0c;Logback 旨在作为流行的 log4j 项目的后续版本&#xff0c;从而恢复 log4j 离开的位置。 另外 slf4j(…

定点整数、小数

文章目录 一、定点整数二、定点小数三、定点小数的加/减运算 一、定点整数 二、定点小数 三、定点小数的加/减运算 对两个定点小数A、B进行加法/减法时&#xff0c;需要先转换为补码 计算机硬件如何做定点小数补码的加法&#xff1a;从最低位开始&#xff0c;按位相加&#x…

栈与队列:设计循环队列

目录 题目&#x1f525;&#xff1a; 数据模型&#xff1a; 本题大意&#xff1a; 思路分析&#xff1a; 代码分析&#xff1a; 一、定义队列 二、初始化、判断队列的空和满⭐ 初始化&#xff1a; 空满的判断&#xff1a; 三、入队和出队&#x1f387; 入队&…

Vue中实现div的任意移动

前言 在系统应用中&#xff0c;像图片&#xff0c;流程预览及打印预览等情况&#xff0c;当前视窗无法全部显示要预览的全部内容&#xff0c;设置左右和上下滚动条后&#xff0c;如果用鼠标拖动滚动条&#xff0c;又不太便利&#xff0c;如何用鼠标随意的移动呢&#xff1f; …

前端面试:如何实现并发请求数量控制?

题目&#xff1a;实现一个并发请求函数concurrencyRequest(urls, maxNum) 要求如下&#xff1a; 要求最大并发数 maxNum;每当有一个请求返回&#xff0c;就留下一个空位&#xff0c;可以增加新的请求;所有请求完成后&#xff0c;结果按照 urls 里面的顺序依次打出&#xff1b;…

.babyk勒索病毒解析:恶意更新如何威胁您的数据安全

导言&#xff1a; 在数字时代&#xff0c;威胁不断进化&#xff0c;其中之一就是.babyk勒索病毒。这种病毒采用高级加密算法&#xff0c;将用户文件锁定&#xff0c;并要求支付赎金以获取解密密钥。本文91数据恢复将深入介绍.babyk勒索病毒的特点、如何应对被加密的数据&#…

【Promise12数据集】Promise12数据集介绍和预处理

【Segment Anything Model】做分割的专栏链接&#xff0c;欢迎来学习。 【博主微信】cvxiayixiao 本专栏为公开数据集的介绍和预处理&#xff0c;持续更新中。 要是只想把Promise12数据集的raw形式分割为png形式&#xff0c;快速导航&#xff0c;直接看2&#xff0c;4标题即可 …

arcgis属性表十进制度转换成度分秒格式--转换坐标注记法

1、有一组点数据&#xff0c;如下&#xff1a; 2、为其添加XY坐标&#xff0c;如下&#xff1a; 打开属性表&#xff0c;可得到对应点的XY的十进制度坐标&#xff0c;如下&#xff1a; 3、将十进制度转换成度分秒格式&#xff0c;如下&#xff0c;使用转换坐标注记法工具&#…

FPGA实现平衡小车(文末开源!!)

FPGA平衡小车 一. 硬件介绍 底板资源: TB6612电机驱动芯片 * 2 MPU6050陀螺仪 WS2812 RGB彩色灯 * 4 红外接收头 ESP-01S WIFI 核心板 微相 A7_Lite Artix-7 FPGA开发板 电机采用的是平衡小车之家的MG310(GMR编码器)电机。底板上有两个TB6612芯片&#xff0c;可以驱动…