最适合新手的SpringBoot+SSM项目《苍穹外卖》实战—(五)员工管理

news2024/9/29 7:31:19

黑马程序员最新Java项目实战《苍穹外卖》,最适合新手的SpringBoot+SSM的企业级Java项目实战。

新增员工

设计 DTO 类

  1. 我们需要根据新增员工接口设计对应的 DTO 类去接收前端传递的参数,前端传递参数列表如下:

    image-20230708205311837

    注意: 当前端提交的数据和实体类中对应的属性差别比较大时,建议使用 DTO 来封装数据。

  2. 进入 sky-pojo 模块,在 com.sky.dto 包下,定义 EmployeeDTO:

    public class EmployeeDTO implements Serializable {
    
        private Long id;
    
        private String username;
    
        private String name;
    
        private String phone;
    
        private String sex;
    
        private String idNumber;
    }
    

编写接口

sky-server下EmployeeController.java 中添加新增员工接口:

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

设置 Header

  1. 项目中使用了 Token 作为身份验证和授权的凭证,用于验证用户的身份和授权用户访问系统中的受保护资源。

    image-20230708222352045

  2. 我们点击【员工登录】接口,在请求体中设置用户登录的账号密码,点击发送,获取后端生成的 Token。

    {
      "password": "123456",
      "username": "admin"
    }
    

    image-20230708222457361

  3. 所有后续的请求都需要在请求头中携带我们生成的 Token,以确保后端进行用户验证。我们在设置中,设置环境,在 Header 中添加我们上一步获取的 Token。

    image-20230708222829890

捕获 SQL 异常

  1. 在员工数据表 employee 中,对 username 字段设置了唯一约束:

    image-20230717200047486

  2. 当我们插入已存在员工姓名时,会出现 SQL 异常:

    java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '11111' for key 'employee.idx_username'
    
  3. 我们需要在全局异常 GlobalExceptionHandler 类中捕获这个异常,处理异常并返回前端结果:

    /**
    * 处理SQL异常
    * @param ex
    * @return
    */
    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
      //Duplicate entry 'zhangsan' for key 'employee.idx_username'
      String message = ex.getMessage();
      if(message.contains("Duplicate entry")){
        String[] split = message.split(" ");
        String username = split[2];
        String msg = username + MessageConstant.ALREADY_EXISTS;
        return Result.error(msg);
      }else{
        return Result.error(MessageConstant.UNKNOWN_ERROR);
      }
    }
    
  4. 再次运行【新增员工】接口,后端返回结果如下:

    {
      "code":0,
      "msg":"'xiaozhi'已存在",
      "data":null
    }
    

ThreadLocal 优化

ThreadLocal 为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不
能访问。

  1. 我们需要在 JwtTokenAdminInterceptor 拦截器中当前登录用户 ID 保存到 ThreadLocal 中,方便后续处理:

    // 在线程变量中保存登录用户id
    BaseContext.setCurrentId(empId);
    
  2. 修改 EmployeeServiceImpl 实现类中的 save() 方法,增加员工时添加创建人的 ID:

    //设置当前记录创建人id和修改人id
    Long createUserId = BaseContext.getCurrentId();
    employee.setCreateUser(createUserId);
    employee.setUpdateUser(createUserId);
    
  3. 当我们在线程池下使用 ThreadLocal 时,需要手动调用 remove() 方法,防止内存泄漏。

员工分页查询

设计 DTO 类

  1. 我们需要根据新增员工接口设计对应的 DTO 类去接收前端传递的参数,前端传递参数列表如下:

    image-20230717210512945

  2. 进入 sky-pojo 模块,在 com.sky.dto 包下,定义 EmployeePageQueryDTO:

    public class EmployeePageQueryDTO implements Serializable {
    
        //员工姓名
        private String name;
    
        //页码
        private int page;
    
        //每页显示记录数
        private int pageSize;
    
    }
    

编写接口

  1. 在 sky-server 下 EmployeeController.java 中添加新增员工分页查询接口:

    /**
    * 员工分页查询
    * @param employeePageQueryDTO
    * @return
    */
    @GetMapping("/page")
    @ApiOperation(value = "员工分页查询")
    public Result<PageResult> page(EmployeePageQueryDTO employeePageQueryDTO){
      log.info("员工分页查询:{}",employeePageQueryDTO);
      PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO);
      return Result.success(pageResult);
    }
    
  2. 在 EmployeeServiceImpl 中实现分页查询逻辑:

    @Override
    public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
      PageHelper.startPage(employeePageQueryDTO.getPage(),employeePageQueryDTO.getPageSize());
      Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
      return new PageResult(page.getTotal(),page.getResult());
    }
    
  3. 在 EmployeeMapper.xml 中编写 SQL 语句:

    <select id="pageQuery" resultType="com.sky.entity.Employee">
      select * from employee
      <where>
        <if test="name != null and name !=''">
          name like concat('%',#{name},'%')
        </if>
      </where>
      order by create_time desc
    </select>
    
  4. Employee 类中使用 @JsonFormat 注解修改时间格式:

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime updateTime;
    
  5. 启动项目,页面测试功能:

    image-20230729181547726

启动禁用员工账号

  1. 在 EmployeeController 员工控制类中编写接口:

        /**
         * 启用、禁用员工账号
         * @param status
         * @param id
         * @return
         */
        @PostMapping("/status/{status}")
        @ApiOperation(value = "启用、禁用员工账号")
        public Result startOrStop(@PathVariable Integer status, Long id){
            log.info("启用禁用员工账号:{},{}",status,id);
            employeeService.startOrStop(status,id);
            return Result.success();
        }
    
  2. 在 EmployeeServiceImpl 实现类中实现功能:

        @Override
        public void startOrStop(Integer status, Long id) {
            Employee employee = Employee.builder().id(id).status(status).build();
            employeeMapper.update(employee);
        }
    
  3. 补充 EmployeeMapper 中的 update SQL语句:

        <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="updateTime != null">update_Time = #{updateTime},</if>
                <if test="updateUser != null">update_User = #{updateUser},</if>
                <if test="status != null">status = #{status},</if>
            </set>
            where id = #{id}
        </update>
    

根据id查询员工信息

  1. 在 EmployeeController 员工控制类中编写接口:

        /**
         * 根据id查询员工
         * @param id
         * @return
         */
        @GetMapping("/{id}")
        @ApiOperation(value = "根据id查询员工")
        public Result<Employee> getById(@PathVariable Long id){
            log.info("根据id查询员工:{},",id);
            Employee employee = employeeService.getById(id);
            return Result.success(employee);
        }
    
  2. 在 EmployeeServiceImpl 实现类中实现功能:

        @Override
        public Employee getById(Long id) {
            Employee employee = employeeMapper.getById(id);
            employee.setPassword("****");
            return employee;
        }
    
  3. 补充 EmployeeMapper 中的 SQL 语句:

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

    编辑员工信息

  4. 在 EmployeeController 中创建 update 方法:

    	/**
         * 编辑员工信息
         * @param employeeDTO
         * @return
         */
        @PutMapping
        @ApiOperation("编辑员工信息")
        public Result update(@RequestBody EmployeeDTO employeeDTO){
            log.info("编辑员工信息:{}", employeeDTO);
            employeeService.update(employeeDTO);
            return Result.success();
        }
    
  5. 在 EmployeeServiceImpl 中实现 update 方法:

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

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

        employeeMapper.update(employee);
    }

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

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

相关文章

C++ 成员初始化列表和new运算符的应用

输出一个学生的学号&#xff0c;姓名&#xff0c;性别和出生年月日 class Date { public:Date(int y, int m, int d) :m_year(y), m_month(m), m_day(d) {}void Print(){cout << m_year << "/" << m_month << "/" << m_day…

第四章 No.1树状数组的原理与使用

文章目录 应用问题原理树状数组练习题241. 楼兰图腾242. 一个简单的整数问题243. 一个简单的整数问题2244. 谜一样的牛 线段树的反面&#xff1a;树状数组原理复杂&#xff0c;实现简单 应用问题 支持两个操作&#xff1a;快速求前缀和任意地修改某个数&#xff0c;时间复杂度…

520 · 一致性哈希 II

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; 题解&#xff1a; class Solution{private:int n;const int mVirtualNodeCount;map<int, int> mVirtualNodeToMachineIdMap;set<int> mVirtualNodeSet;public:Solution(int n…

SpringBoot的三层架构以及IOCDI

目录 一、IOC&DI入门 二、三层架构 数据库访问层 业务逻辑层 控制层 一、IOC&DI入门 在软件开发中&#xff0c;IOC&#xff08;Inversion of Control&#xff09;和DI&#xff08;Dependency Injection&#xff09;是密切相关的概念。 IOC&#xff08;控制反转&a…

CAN学习笔记2:CAN简介

CAN 1 概述 CAN(Controller Area Network),是 ISO 国际标准化的串行通信协议,目的是适应汽车“减少线束的数量”、“通过多个网络进行大量数据的高速传输”的需求。 低速 CAN(ISO11519)通信速率 10~125Kbps&#xff0c;总线长度可达 1000米. 高速 CAN(ISO11898)通信速率 125~…

cnn卷积神经网络(基础)

convolutional neural networks 特征提取&#xff08;卷积、下采样&#xff09;->分类器 &#xff08;全连接&#xff09; 卷积过程 依次进行数乘 &#xff08;每个相同位置上的数字相乘再加和&#xff09; 左右数乘矩阵channel数量要一样&#xff0c;输出得到一个通道 卷…

吴师傅教你几招极速清理C盘,高能操作绝不让你失望!

电脑使用久了&#xff0c;C盘堆积的垃圾过多&#xff1b;每天上网会给电脑带来很多临时文件&#xff0c;这些垃圾文件不清理掉时间久了就会影响到电脑的运行速度&#xff1b;也会导致C盘变红&#xff0c;空间不足。那么&#xff0c;电脑C盘满了如何清理呢&#xff1f;教你几招极…

SpringBoot 如何进行 统一异常处理

在Spring Boot中&#xff0c;可以通过自定义异常处理器来实现统一异常处理。异常处理器能够捕获应用程序中抛出的各种异常&#xff0c;并提供相应的错误处理和响应。 Spring Boot提供了ControllerAdvice注解&#xff0c;它可以将一个类标记为全局异常处理器。全局异常处理器能…

NICE-SLAM: Neural Implicit Scalable Encoding for SLAM论文阅读

论文信息 标题&#xff1a;NICE-SLAM: Neural Implicit Scalable Encoding for SLAM 作者&#xff1a;Zihan Zhu&#xff0c; Songyou Peng&#xff0c;Viktor Larsson — Zhejiang University 来源&#xff1a;CVPR 代码&#xff1a;https://pengsongyou.github.io/nice-slam…

ARM单片机中断处理过程解析

前言 中断&#xff0c;在单片机开发中再常见不过了。当然对于中断的原理和执行流程都了然于胸&#xff0c;那么对于ARM单片机中断的具体处理行为&#xff0c;你真的搞清楚了吗&#xff1f; 今天来简单聊一聊&#xff0c;ARM单片机中断处理过程中的具体行为是什么样的&#xf…

spring5源码篇(13)——spring mvc无xml整合tomcat与父子容器的启动

spring-framework 版本&#xff1a;v5.3.19 文章目录 整合步骤实现原理ServletContainerInitializer与WebApplicationInitializer父容器的启动子容器的启动 相关面试题 整合步骤 试想这么一个场景。只用 spring mvc&#xff08;确切来说是spring-framework&#xff09;&#x…

Windows环境下安装及部署Nginx

一、安装Nginx教程 1、官网下载地址&#xff1a;https://nginx.org/en/download.html 2、下载教程&#xff1a;选择Stable version版本下载到本地 3、下载完成后&#xff0c;解压放入本地非中文的文件夹中&#xff1a; 4、启动nginx&#xff1a;双击nginx.exe&#xff0c;若双击…

Vue 3:玩一下web前端技术(五)

前言 本章内容为VUE语法的简单学习与相关语法讨论。 上一篇文章地址&#xff1a; Vue 3&#xff1a;玩一下web前端技术&#xff08;四&#xff09;_Lion King的博客-CSDN博客 下一篇文章地址&#xff1a; Vue 3&#xff1a;玩一下web前端技术&#xff08;六&#xff09;_L…

算法与数据结构(四)--排序算法

一.冒泡排序 原理图&#xff1a; 实现代码&#xff1a; /* 冒泡排序或者是沉底排序 *//* int arr[]: 排序目标数组,这里元素类型以整型为例; int len: 元素个数 */ void bubbleSort (elemType arr[], int len) {//为什么外循环小于len-1次&#xff1f;//考虑临界情况&#xf…

自动驾驶感知系统-全球卫星定位系统

卫星定位系统 车辆定位是让无人驾驶汽车获取自身确切位置的技术&#xff0c;在自动驾驶技术中定位担负着相当重要的职责。车辆自身定位信息获取的方式多样&#xff0c;涉及多种传感器类型与相关技术。自动驾驶汽车能够持续安全可靠运行的一个关键前提是车辆的定位系统必须实时…

为什么你的独立站有流量没转化?如何做诊断检查?

新店的创业初期&#xff0c;即使网站有流量&#xff0c;但是销售额为零的情况也常有发生。如果你确定流量是高质量的&#xff0c;寻找阻止潜在客户购买的具体因素可能会感到困难重重。 从“立即购买”按钮的色彩选择这样的细节&#xff0c;到构建品牌故事这样的大计划&#xf…

开发一个RISC-V上的操作系统(四)—— 内存管理

目录 往期文章传送门 一、内存管理简介 二、Linker Script 链接脚本 三、动态分配内存 四、测试 往期文章传送门 开发一个RISC-V上的操作系统&#xff08;一&#xff09;—— 环境搭建_riscv开发环境_Patarw_Li的博客-CSDN博客 开发一个RISC-V上的操作系统&#xff08;二…

springboot创建并配置环境(三) - 配置扩展属性(上集)

文章目录 一、介绍二、配置文件application.yml 一、介绍 在上一篇文章&#xff1a;springboot创建并配置环境(二) - 配置基础环境中&#xff0c;我们介绍了springboot如何配置基础环境变量。本篇文章讨论如何处理配置文件。即来自不同位置的配置属性&#xff0c;如&#xff1…

chatglm2外挂知识库问答的简单实现

一、背景 大语言模型应用未来一定是开发热点&#xff0c;现在一个比较成功的应用是外挂知识库。相比chatgpt这个知识库比较庞大&#xff0c;效果比较好的接口。外挂知识库大模型的方式可以在不损失太多效果的条件下获得数据安全。 二、原理 现在比较流行的一个方案是langcha…

OpenLayers入门,OpenLayers使用瓦片加载事件实现瓦片加载进度条,进度条根据瓦片加载数量自动更新进度,加载完毕后隐藏进度条

专栏目录: OpenLayers入门教程汇总目录 前言 本章主要讲解OpenLayers如何使用瓦片加载事件(tileloadstart)、瓦片加载完成事件(tileloadend)以及瓦片加载错误事件(tileloadend)。 并通过OpenLayers使用瓦片加载事件通过实现瓦片加载进度条的案例,实现进度条根据瓦片加…