苍穹外卖day02——员工管理功能代码开发+分类管理代码导入

news2024/11/28 12:42:47

目录

新增员工——需求分析与设计

 产品原型

 接口设计:

数据库设计:

新增员工——代码开发

 在Controller层中

 在Service层中

 在Mapper层中

 功能测试

接口文档测试:

 前后端联调测试:

 新增员工——代码完善

​编辑

第一个问题 

第二个问题

员工分页查询

需求分析与设计

产品原型如下

接口设计

​编辑

 代码开发

在Controller层中

在Service层中

在Mapper层中

功能测试

swagger接口文档测试

 前后端联调测试

代码完善

启用,禁用员工账号——需求分析与设计

​编辑 接口设计

启用,禁用员工账号——代码开发和功能测试

在Controller层中

在Service层中

在Mapper层中

功能测试

接口文档测试 

前后端联调测试 

编辑员工——需求分析与设计

产品原型:

 接口设计

 编辑员工——代码开发

在Controller层中

在Service层中

在Mapper层中

功能测试

前后端联调测试 

导入分类管理功能代码

产品原型

 数据库设计表


新增员工——需求分析与设计

 产品原型

 接口设计:

数据库设计:

新增员工——代码开发

DTO是传输数据的实体类,而不是某一个表格的实体类。

 在Controller层中

 EmployeeController中

    /*
    *
    *
    * 新增员工
    * */
    @PostMapping
    @ApiOperation("新增员工")
    public Result save(@RequestBody EmployeeDTO employeeDTO){
        log.info("新增员工:{}",employeeDTO);
        employeeService.save(employeeDTO);
        return Result.success();
    }

 在Service层中

 定义一个新的接口方法


    /**
     * 新增员工业务方法
     * @param employeeDTO
     */
    void save(EmployeeDTO employeeDTO);

 接口实现类新增方法,此处创建人和修改人id后面再解决。

@Override
    public void save(EmployeeDTO employeeDTO) {
        Employee employee=new Employee();
        //两个实体有很多属性名都一样,不一个一个set的话,可以通过对象的属性拷贝
        BeanUtils.copyProperties(employeeDTO,employee);

        //设置账号状态,默认正常状态1,0锁定,为了方便后期维护,使用一个常量类
        employee.setStatus(StatusConstant.ENABLE);

        //设置密码,默认密码123456
        employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));

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

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

        employeeMapper.insert(employee);
    }

 在Mapper层中

    /**
     * 插入员工数据
     * @param employee
     */
    @Insert("insert into employee (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);

 功能测试

接口文档测试:

在调试界面设置好参数,点击发送 后返回一个401,没有成功返回,这里是被拦截器拦截了。

 会校验jwt令牌 ,这里因为没有令牌,所以token为空,返回的是401

 首先要获取一个令牌,在登录接口正常获取即可。

 获取到token之后在文档管理——>全局参数设置里面配置一个token属性。

这里name=token是因为后端项目配置文件里面配置的一个属性就是token,项目会自动取出这个token 

再次发送调试成功返回 

 前后端联调测试:

 数据库成功多出两条数据

 新增员工——代码完善

第一个问题 

将插入重复员工时报的错误异常放进全局异常处理器进行处理 

SQLIntegrityConstraintViolationException

    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
        // Duplicate entry 'yhy' for key 'employee.idx_username'
        String message=ex.getMessage();
        if(message.contains("Duplicate entry")){
            String[] s = message.split(" ");
            String username = s[2];
            String msg=username+ MessageConstant.ALREADY_EXISTS;
            return Result.error(msg);
        }else{
            return Result.error(MessageConstant.UNKNOWN_ERROR);
        }
    }

再次测试

第二个问题


 

总的就是获取token中间的字段进行解析之后就可以获取登录用户ID了

客户端发起的每一次请求都是一次单独的线程。

这里项目已经提前封装好了ThreadLocal的常用方法 

 在拦截器当中将取出的ID存进暂存区

            BaseContext.setCurrentId(empId);

在服务层代码中取出


        //设置当前记录创建人id和修改人id
        // TODO 后期改为当前登录用户的id
        employee.setCreateUser(BaseContext.getCurrentId());
        employee.setUpdateUser(BaseContext.getCurrentId());

完成一个小功能的代码记得及时存储推送到云端。

员工分页查询

需求分析与设计

产品原型如下

接口设计

 代码开发

设计DTO,传输数据格式。

分页查询的响应数据因为有两个对象,所以再封装一次。然后返回一个Result<PageResult>对象。 

 

 此处使用到一个mybatis提供的分页查询的插件,依赖如下。

            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper}</version>
            </dependency>

在Controller层中

此处是Query参数,所以不需要@Requestbody注解返回的PageResult对象要封装层Result风格。

    /**
     * 员工分页查询
     * @param employeePageQueryDTO
     * @return
     */
    @GetMapping("/page")
    @ApiOperation("员工分页查询")
    public Result<PageResult>page( EmployeePageQueryDTO employeePageQueryDTO){
        log.info("员工分页查询参数为{}",employeePageQueryDTO);
       PageResult pageResult=employeeService.pageQuery(employeePageQueryDTO);
        return Result.success(pageResult);
    }

在Service层中

这里用到了PageHeloer插件,要封装成pageResult对象还要将查询结果里面的数据取出来。

此处startPage方法和pageQuery方法看似没有交集,但是在底层是通过ThreadLocal对象共享了一部分数据。后面开始分页查询之前就已经通过ThreadLocal取出了页码和每页记录数,然后动态的拼接上limit关键字。

    /**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    @Override
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
        //select * from employee limit 0,10
        //开始分页查询,传了个页码和每页的记录数
        PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
        //此处Page对象是PageHelper提供的。
        Page<Employee> page=employeeMapper.pageQuery(employeePageQueryDTO);

        long total = page.getTotal();
        List<Employee> records = page.getResult();

        return new PageResult(total,records);
    }

在Mapper层中

这条查询用的不是注解开发,用的是xml配置文件开发,所以还需要在Resources目录下准备对应的xml文件。


    /**
     * 分页查询
     * @param employeePageQueryDTO
     * @return
     */
    Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);

在配置文件中已经配置好了这个xml开发

mybatis:
  #mapper配置文件
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.sky.entity
  configuration:
    #开启驼峰命名
    map-underscore-to-camel-case: true

在EmployeeMapper.xml文件里面

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.EmployeeMapper">
    <select id="pageQuery" resultType="com.sky.entity.Employee">
        select * from employee
        <where>
            <if test="name != null and name != ''">
                and name like concat('%',#{name},'%')
            </if>
        </where>
        order by create_time desc
    </select>
</mapper>

功能测试

swagger接口文档测试

 

 控制台输出

 前后端联调测试

 因为返回的日期数据用的是数据格式,所以前端的时间格式看着很别扭.

代码完善

方式一:

加上注解 

 

再次测试看见数据格式有了变化。

 第二种方式

准备一个对象转换器 ,主要进行序列化和反序列化操作

/**
 * 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
 * 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
 * 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
 */
public class JacksonObjectMapper extends ObjectMapper {

    public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
    //public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";
    public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

    public JacksonObjectMapper() {
        super();
        //收到未知属性时不报异常
        this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);

        //反序列化时,属性不存在的兼容处理
        this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        SimpleModule simpleModule = new SimpleModule()
                .addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
                .addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
                .addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
                .addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));

        //注册功能模块 例如,可以添加自定义序列化器和反序列化器
        this.registerModule(simpleModule);
    }
}

在配置类中

    /**
     * 扩展springMVC框架的消息转换器,可以
     * @param converters
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("扩展消息转换器...");
        //创建一个消息转换器对象
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        //需要为消息转换器设置一个对象转换器,对象转换器可以将java对象序列化为json数据
        converter.setObjectMapper(new JacksonObjectMapper());
        //将自己的消息转换器加入容器中,并设定优先级为0,最高优先级
        converters.add(0,converter);
    }

接口文档测试:

 前后端联调测试

都没有问题了。

最后还要记得推送云端。

启用,禁用员工账号——需求分析与设计

 接口设计

需要一个路径参数和一个Query参数

 

启用,禁用员工账号——代码开发和功能测试

在Controller层中

针对查询类的操作需要返回data数据,则要加上泛型,非查询类的就不需要了。

 


    /**
     * 路径参数通过PathVariable注解获取,Query参数只要name保持一致即可
     * @param status
     * @param id
     * @return
     */
    @PostMapping("/status/{status}")
    @ApiOperation("启用禁用员工账号")
    public Result startOrStop(@PathVariable("status") Integer status,Long id){
        log.info("启用禁用员工账号{},{}",status,id);
        employeeService.startOrStop(status,id);
        return Result.success();
    }

在Service层中

    /**
     * 启用禁用员工账号
     * @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);
    }

在Mapper层中

这里用的是动态SQL写法,需要xml文件

    /**
     * 根据主键动态修改属性
     * @param employee
     */
    void update(Employee employee);
    <!--这里因为配置文件里面已经扫描到了Employee,所以不用写完整的类名可以写个别名-->
    <update id="update" parameterType="Employee">
        update employee
        <set>
            <if test="name != null"> name = #{name},</if>
            <if test="username != null"> username = #{username},</if>
            <if test="password != null"> password = #{password},</if>
            <if test="phone != null"> phone = #{phone},</if>
            <if test="sex != null"> sex = #{sex},</if>
            <if test="idNumber != null"> id_number = #{idNumber},</if>
            <if test="status != null"> status = #{status},</if>
            <if test="updateTime != null"> update_Time = #{updateTime},</if>
            <if test="updateUser != null"> update_User = #{updateUser},</if>
        </set>
        where id =#{id}
    </update>

功能测试

接口文档测试 

数据库数据修改成功 

前后端联调测试 

成功修改。

编辑员工——需求分析与设计

编辑界面需要点击修改然后查询回显员工信息然后根据需要进行修改再保存更新数据库。

产品原型:

 接口设计

一个接口是查询的接口,一个接口是更新的接口。

 

 编辑员工——代码开发

 可以看见id是通过路径参数传参。

在Controller层中

 /**
     * 根据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("编辑员工信息")
    public Result update(@RequestBody  EmployeeDTO employeeDTO)
    {
        log.info("编辑员工信息{}",employeeDTO);
        employeeService.update(employeeDTO);
        return Result.success();
    }

在Service层中

    /**
     * 根据id查询员工
     * @param id
     * @return
     */
    @Override
    public Employee getBYId(Long id) {
      Employee employee= employeeMapper.getById(id);
      employee.setPassword("****");//防止密码泄露
      return employee;
    }

    /**
     * 编辑员工信息
     * @param employeeDTO
     */
    @Override
    public void update(EmployeeDTO employeeDTO) {
        Employee employee=new Employee();
        //对象属性拷贝,这样就可以使用上面启用禁用那里的update语句
        BeanUtils.copyProperties(employeeDTO,employee);
        employee.setUpdateTime(LocalDateTime.now());
        employee.setUpdateUser(BaseContext.getCurrentId());
        employeeMapper.update(employee);
    }

在Mapper层中

这里因为update方法在启用禁用部分已经写过了,所以这里不再写一次了

    /**
     * 根据id查询员工信息
     * @param id
     * @return
     */
    @Select("select * from employee where id =#{id}")
    Employee getById(Long id);

功能测试

查询回显成功

前后端联调测试 

记得推送代码

导入分类管理功能代码

产品原型

 数据库设计表

导入分类管理模块的代码之后成功进行前后端联调测试

 记得git push

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

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

相关文章

PostgreSQL考试难不难 ?

当涉及到PostgreSQL考试的详细难度&#xff0c;以下是一些可能涉及的主题和考点&#xff0c;这些主题在不同的考试中可能有所不同&#xff1a; 1.数据库基础知识&#xff1a;数据库的基本概念、关系型数据库模型、表、字段、主键、外键等。 2.SQL语言&#xff1a;对SQL语言的掌…

数据集——个人收集标注与使用过的数据集

前言 这是一个我个人在工作和学习中使用过以数据集的一部分&#xff0c;有语义分割&#xff0c;目标识别&#xff0c;人像抠图等几个大类&#xff0c;这只是我用过数据集中的一部分&#xff0c;这些数据集有小一部分是来源自网络&#xff0c;很大一部分都是我自己收集。 一、…

【动手学深度学习】--05.权重衰退

文章目录 权重衰退1.原理1.1使用均方范数作为硬性限制1.2使用均方范数作为柔性限制1.3对最优解的影响1.4参数更新法则 2.从零开始实现权重衰退2.1初始化模型参数2.2定义L2范数惩罚2.3训练2.4忽略正则化直接训练2.5使用权重衰退 3.简洁实现 权重衰退 学习视频&#xff1a;权重衰…

在网格化数据集上轻松执行 2D 高通、低通、带通或带阻滤波器研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

ModaHub魔搭社区:AI原生云向量数据库Zilliz Cloud设置白名单

目录 前提条件 操作步骤 下一步 在 Zilliz Cloud 中,白名单是针对项目的安全设置,适用于项目下的所有集群。设置白名单后,仅白名单中的 IP 地址可以访问您项目下的所有集群。白名单能够有效降低受到恶意攻击的风险 本教程将介绍如何设置白名单。 前提条件 确保满足以…

EasyX测试布局代码

#include <iostream> #include <algorithm> #include <graphics.h> // 引用图形库头文件 #include <conio.h> #include <unordered_map> #include <Windows.h> #include "layout/LayoutSystem.h"#define DEFAULT_PANELS_LAYOUT…

谈二级索引

前提&#xff1a; 在数据库中&#xff0c;1、索引分为聚簇索引和非聚簇索引两类。2、所有索引的数据结构都是树&#xff0c;查找树上的节点数据时通过用二分法来锁定数据范围&#xff0c;指定数据排序的规则&#xff0c;比如&#xff1a;有小到大&#xff0c;对比之后最终确定…

Sequencer使用心得

在关卡序列中设置了触发蓝图的关键帧&#xff0c;为什么播放的时候没有触发蓝图事件呢&#xff1f; 在关卡序列中触发蓝图&#xff0c;一般是将蓝图添加到轨道中&#xff0c;设置触发器&#xff0c;在对应的关键帧中&#xff0c;绑定蓝图事件。 一般的话&#xff0c;点击播…

栈、队列、优先级队列详解【c++】

目录 &#x1f3c0;stack的介绍和使用⚽stack的介绍⚽stack的使用 &#x1f3c0;queue的介绍和使用⚽queue的介绍⚽queue的使用 &#x1f3c0;priority_queue的介绍和使用⚽priority_queue的介绍⚽priority_queue的使用 &#x1f3c0;总结 &#x1f3c0;stack的介绍和使用 ⚽s…

尝试-InsCode Stable Diffusion 美图活动一期

一、 Stable Diffusion 模型在线使用地址&#xff1a; https://inscode.csdn.net/inscode/Stable-Diffusion 二、模型相关版本和参数配置&#xff1a; 活动地址 三、图片生成提示词与反向提示词&#xff1a; 提示词&#xff1a;realistic portrait painting of a japanese…

OPENMV的形状和颜色组合识别

使用openmv&#xff0c;通过阈值颜色和形状来去真假宝藏。调试过程发现颜色的阈值比较重要&#xff0c;因为不准的话&#xff0c;它会把一些颜色相近的物体也识别了。识别的精度有待提高&#xff0c;可以使用YOLOV5来精确识别&#xff0c;奈何本人没精力来弄这个。 打开机器视觉…

Proxmox VE 为 Windows 虚拟机添加硬盘遇到的问题

环境&#xff1a;PVE 8.x、Windows 11/Windows Server 2019 &#x1f449;问题一&#xff1a; 为 windows 虚拟机添加磁盘&#xff0c;重启虚拟机后&#xff08;在 windows 系统中重启&#xff09;磁盘未能生效&#xff0c;并显示为橘色。 ❗橘色 意味需要重启VM才能生效&…

BIO实战、NIO编程与直接内存、零拷贝深入辨析-02

网络通信编程基本常识 什么是 Socket &#xff1f; Socket 是应用层与 TCP/IP 协议族通信的中间软件抽象层&#xff0c;它是一组接口&#xff0c;一般由操作 系统提供。在设计模式中&#xff0c;Socket 其实就是一个门面模式&#xff0c;它把复杂的 TCP/IP 协议处理和…

RocketMQ学习笔记(基础篇)

目录 RocketMQ简介 单Master模式 多Master模式 多Master多Slave模式&#xff08;异步&#xff09; 多Master多Slave模式&#xff08;同步&#xff09; 双主双从集群 事务消息 事务消息发送及提交 事务补偿 事务消息状态 RocketMQ高级功能 消息存储 存储介质 消息的…

vue upload 下载

目录 上传 下载 get post 对象/文件流 download处理返回 文件流 axios.post 封装axios 后端直接返回文件流&#xff0c;打开下载文件是 [object Object]&#xff0c;将res改成res.data即可 1.请求设置类型responseType: blob&#xff08;如果没有设置&#xff0c;打…

14_Linux设备树下的platform驱动编写

目录 设备树下的platform驱动简介 运行测试 设备树下的platform驱动简介 platform驱动框架分为总线、设备和驱动,其中总线不需要我们这些驱动程序员去管理&#xff0c;这个是Linux内核提供的,我们在编写驱动的时候只要关注于设备和驱动的具体实现即可。在没有设备树的Linux内…

1770_VirtualBox下安装Debian

全部学习汇总&#xff1a; GreyZhang/little_bits_of_linux: My notes on the trip of learning linux. (github.com) 作为我自己的日常使用&#xff0c;Debian基本上没有出现过。最多是让它运行在某个设备上作为一个服务的平台&#xff0c;因为很多东西我懒得去配置。 Debia…

前端 | (二)各种各样的常用标签 | 尚硅谷前端html+css零基础教程2023最新

学习来源&#xff1a;尚硅谷前端htmlcss零基础教程&#xff0c;2023最新前端开发html5css3视频 文章目录 &#x1f4da;HTML排版标签&#x1f4da;HTML语义化标签&#x1f4da;块级元素与行内元素&#x1f4da;文本标签&#x1f407;常用的文本标签&#x1f407;不常用的文本标…

模版模式在Spring中的应用

前言 模式模式在Spring中的应用较多&#xff0c;这里结合JdbcTemplate的源码来和大家一起学习下&#xff0c;更加深刻滴认识下模版模式&#xff0c;以便在日常开发中&#xff0c;能灵活运用模版模式&#xff0c;来减少重复代码&#xff0c;增强代码的可拓展性。 何为模版模式…