• 瑞吉外卖学习笔记3


    瑞吉外卖学习笔记3

    公共字段自动填充功能

    问题分析
    前面我们已经完成了后台系统的员工管理功能开发,在新增员工时需要设置创建时间、创建人、修改时间、修改人等字段,在编辑员工时需要设置修改时间和修改人等字段。这些字段属于公共字段,也就是很多表中都有这些字段,如下:
    在这里插入图片描述
    在这里插入图片描述
    表中的公共字段为:
    在这里插入图片描述
    能不能对于这些公共字段在某个地方统一处理,来简化开发呢?
    答案就是使用Mybatis Plus提供的公共字段自动填充功能。

    公共字段自动填充-代码实现并测试

    代码实现
    Mybatis Plus公共字段自动填充,也就是在插入或者更新的时候为指定字段赋予指定的值,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码。
    具体实现
    1、在实体类的属性上加入@TableField注解,指定自动填充的策略
    2、照框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectHandler接口

    在公共属性上添加@TableField注解
    @TableField(fill = FieldFill.INSERT),表示插入时填充字段
    @TableField(fill = FieldFill.INSERT_UPDATE),表示插入和更新时填充字段
    在这里插入图片描述

    再common包下面,自定义元数据对象处理器(初步测试)

    package com.itzq.reggie.common;
    
    import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.reflection.MetaObject;
    import org.springframework.stereotype.Component;
    
    @Component
    @Slf4j
    public class MyMetaObjectHandler implements MetaObjectHandler {
    
        @Override
        public void insertFill(MetaObject metaObject) {
            log.info("公共字段自动填充【insert】");
            log.info(metaObject.toString());
        }
    
        @Override
        public void updateFill(MetaObject metaObject) {
            log.info("公共字段自动填充【update】");
            log.info(metaObject.toString());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    为了进一步验证代码正确与否我们再这里进行断点DEBUG测试
    在这里插入图片描述
    进入界面点击修改员工数据
    在这里插入图片描述
    点击保存
    在这里插入图片描述
    **观察:**发现前端传到服务端的数据,updateUser与updateTime数据在controller中的对应方法中被修改;
    在这里插入图片描述

    注释掉save方法的部分代码
    在这里插入图片描述
    修改MyMetaObjectHandler类中部分代码

    先将createUser,updateUser属性的初始值设置为1,后面会讲解如何获取当前user

    package com.itzq.reggie.common;
    
    import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.reflection.MetaObject;
    import org.springframework.stereotype.Component;
    
    import java.time.LocalDateTime;
    
    @Component
    @Slf4j
    public class MyMetaObjectHandler implements MetaObjectHandler {
    
        @Override
        public void insertFill(MetaObject metaObject) {
            log.info("公共字段自动填充【insert】");
            log.info(metaObject.toString());
            metaObject.setValue("createTime", LocalDateTime.now());
            metaObject.setValue("updateTime", LocalDateTime.now());
            metaObject.setValue("createUser", new Long(1));
            metaObject.setValue("updateUser", new Long(1));
        }
    
        @Override
        public void updateFill(MetaObject metaObject) {
            log.info("公共字段自动填充【update】");
            log.info(metaObject.toString());
        }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    添加断点进行测试:
    在这里插入图片描述
    DEBUG方式重启
    来到添加员工页面,输入数据,点击保存
    在这里插入图片描述
    开始走断点走到最后我们发现我们也将之前为null的字符给填充了
    在这里插入图片描述
    修改员工信息时也需要填充

    	@Override
        public void updateFill(MetaObject metaObject) {
            log.info("公共字段自动填充【update】");
            log.info(metaObject.toString());
            metaObject.setValue("updateTime", LocalDateTime.now());
            metaObject.setValue("updateUser", new Long(1));
        }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    添加断点重启并测试
    在这里插入图片描述
    再执行断点前,我们通过DEBUG方式进行分析
    在这里插入图片描述
    在这里插入图片描述

    公共字段自动填充-功能完善

    在学习ThreadLocal之前,我们需要先确认一个事情,就是客户端发送的每次http请求,对应的在服务端都会分配一个新的线程来处理,在处理过程中涉及到下面类中的方法都属于相同的一个线程:
    1、LoginCheckFilter的doFilter方法
    2、EmployeeController的update方法
    3、MyMetaObjectHandler的updateFill方法

    可以在上面的三个方法中分别加入下面代码(获取当前线程id) :
    4. long id = Thread.currentThread().getId();
    5. log.info(“MyMetaObjectHandler线程id为:{}”,id);

    LoginCheckFilter的doFilter方法
    在这里插入图片描述

    EmployeeController的update方法
    在这里插入图片描述
    MyMetaObjectHandler的updateFill方法
    在这里插入图片描述
    启动项目,在修改员工的页面中,点击保存;

    控制台上显示三条日志信息,表明类中的方法都属于相同的一个线程
    在这里插入图片描述

    什么是ThreadLocal?
    1、ThreadLocal并不是一个Thread,而是Thread的局部变量
    2、当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本
    3、所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本
    4、ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。

    ThreadLocal常用方法:
    1、public void set(T value) 设置当前线程的线程局部变量的值
    2、public T get() 返回当前线程所对应的线程局部变量的值

    使用流程
    我们可以在LoginCheckFilter的doFilter方法中获取当前登录用户id,并调用ThreadLocal的set方法来设置当前线程的线程局部变量的值(用户id),然后在MyMetaObjectHandler的updateFill方法中调用ThreadLocal的get方法来获得当前线程所对应的线程局部变量的值(用户id)。

    代码实现
    在common包下添加BaseContext类
    **作用:**基于ThreadLocal封装工具类,用于保护和获取当前用户id
    在这里插入图片描述

    package com.peihj.reggie.common;
    
    /**
     * 基于ThreadLocal封装工具类,用户保存和获取当前登录用户id
     */
    public class BaseContext {
        private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
    
        /**
         * 设置值
         * @param id
         */
        public static void setCurrentId(Long id){
            threadLocal.set(id);
        }
    
        /**
         * 获取值
         * @return
         */
        public static Long getCurrentId(){
            return threadLocal.get();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    在LoginCheckFilter类中添加代码:
    在这里插入图片描述
    在MyMetaObjectHandler类中,修改部分代码:

    package com.peihj.reggie.common;
    
    import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.ibatis.reflection.MetaObject;
    import org.springframework.stereotype.Component;
    import java.time.LocalDateTime;
    
    /**
     * 自定义元数据对象处理器
     */
    @Component
    @Slf4j
    public class MyMetaObjecthandler implements MetaObjectHandler {
        /**
         * 插入操作,自动填充
         * @param metaObject
         */
        @Override
        public void insertFill(MetaObject metaObject) {
            log.info("公共字段自动填充[insert]...");
            log.info(metaObject.toString());
            metaObject.setValue("createTime", LocalDateTime.now());
            metaObject.setValue("updateTime",LocalDateTime.now());
            metaObject.setValue("createUser", BaseContext.getCurrentId());
            metaObject.setValue("updateUser",BaseContext.getCurrentId());
           
        }
    
        /**
         * 更新操作,自动填充
         * @param metaObject
         */
        @Override
        public void updateFill(MetaObject metaObject) {
            log.info("公共字段自动填充[update]...");
            log.info(metaObject.toString());
    
            long id = Thread.currentThread().getId();
            log.info("线程id为:{}",id);
    
            metaObject.setValue("updateTime",LocalDateTime.now());
    //        metaObject.setValue("updateUser",new Long(1));
            metaObject.setValue("updateUser",BaseContext.getCurrentId());
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在这里插入图片描述
    测试
    重启登录一个新的员工账号
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    发现以下字段添加成功,同理根据代码逻辑推断,更新用户操作会更新表中的updateTime,updateUser字段

    参考

    https://blog.csdn.net/eadzsdad/article/details/124231440

  • 相关阅读:
    CSS读书笔记
    从0开始学习JavaScript--JavaScript中的集合类
    Vue3 从入门到放弃 (第五篇.组件事件与v-model使用)
    什么是串行通信?
    Solon 1.7 重要发布,更现代感的应用开发框架
    微机-------输入/输出接口(第六章)
    leetcode 面试题 04.01. 节点间通路 BFS、DFS
    Python实用脚本【二】
    C_3练习题
    c语言练习73:统计位数为偶数的数字
  • 原文地址:https://blog.csdn.net/weixin_45522528/article/details/126210577