SpringBoot+MyBatis-plus 瑞吉外卖项目 Day05

SpringBoot+MyBatis-plus 瑞吉外卖项目 Day05

关于公共字段的分析与简化处理

其实我们在项目中可以发现我们在每一次的操作用户(添加,修改)用户的时候,都会对公共的字段进行更新,比如在添加用户的时候我们会对一下的字段进行更新

//用户的创建时间与更新时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
//创建与更新用户的用户ID
employee.setCreateUser(empID);
employee.setUpdateUser(empID);

我们在更新用户的时候会对以下的字段进行更新

//更新当前的修改者
employee.setUpdateUser(empID);
//更新当前的修改时间
employee.setUpdateTime(LocalDateTime.now());

对用这种进行相同操作的公共字段我们可不可提取出来,单独的进行自动处理赖?没错我们的MyBatis-Plus举手说这个我可以,交给我。

我们的MP给我们提供了便捷的 公共字段自动填充 功能,可以直接将公共的字段提取出来,交付于我们的MP处理。

对于实现MP的自动填充我们需要的只有两步:

  1. 在需要提取的公共字段的实体类中添加@TableField注解,指定自动填充的策略
  2. 按照框架的要求编写元数据对象的处理器,在此类中为统一公共字段赋值,此类需要实现MetaObjectHadler接口

公共的字段中添加不同的更新处理注解

对应实体类的TableField注解添加

//表示插入时填充字段
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime; //创建时间

@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime; //修改时间

@TableField(fill = FieldFill.INSERT)
private Long createUser; //创建者

//表示插入和更新时填充字段
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser; //修改者

SpringBoot+MyBatis-plus 瑞吉外卖项目 Day05_第1张图片

创建自定义的MetaObjectHadler处理

@Controller
@Slf4j
public class MyMethObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段填充【insert】");
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("createUser", new Long(1l));
        metaObject.setValue("updateUser", new Long(1l));
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段填充【update】");
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", new Long(1l));
    }
}

这里其实我们的发现存在一个比较明显的问题的就是,我们无法获取用户的id信息

这里就需要引进一个ThreaLocal。在引入ThreaLocal之前我们先需要先观察确定一下,每一次客户端发送Http请求的时候,与之对应的会给服务端分配一个新的线程进行处理,因次在处理的过程当中,只要是涉及到config包下,自定义配置类中的方法都是数据同一个线程的处理。

为了验证,我们可以在每一个的类中都加入一个 提取当前的线程的id的方法,进行测试。

  1. LoginCheckFilter的doFilter方法
  2. EmployeeController的update方法
  3. MyMetaObjectHandler的updateFill方法

分别在以下类的调用的方法中加入 日志打印发现,调用者三个类时,调用的都是相同的一个线程

image-20220826152045263

SpringBoot+MyBatis-plus 瑞吉外卖项目 Day05_第2张图片

关于ThreadLocal线程的概述

SpringBoot+MyBatis-plus 瑞吉外卖项目 Day05_第3张图片

  • 可以参考博主:我叫大魔王-多线程中的ThreadLocal 详解

关于ThreadLocal方法的使用详解

public T get() { } // 用来获取ThreadLocal在当前线程中保存的变量副本
public void set(T value) { } //set()用来设置当前线程中变量的副本
public void remove() { } //remove()用来移除当前线程中变量的副本
protected T initialValue() { } //initialValue()是一个protected方法,一般是用来在使用时进行重写的

其实简单点来说就是,由于每一次的前端完整的一次请求,**LoginCheckFilter的doFilter**类中的方法都会启动一个新线程,并且该线程与

EmployeeController中的updateMyMetaObjectHandler中的updateFill中启动的线程是同一个,因为我们可以通过**LoginCheckFilter的doFilter** ,为ThreadaLocal 设置一个当前的线程中的当前用户的副本,然后在**MyMetaObjectHandler**中取出当前用户

  • 封装一个ThradLocal的对象获取类

    public class BaseContext {
        public static ThreadLocal<Long> threadLocal=new InheritableThreadLocal<>();
        public Long getContextId(){
            return threadLocal.get();
        }
        public void setContextId(Long id){
            threadLocal.set(id);
        }
    }
    

分类管理

对于分管理这部分其实与之前的部门管理之前没有什么大的区别,唯一需要注意的就是,我们的发现我们的后台解析**LocalDateTime**格式的数据时出现了问题,数据格式不再是 2022-08-17 10:37:37的形式而是[2022, 8, 26, 17, 27, 28]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g6lmUBub-1661515318176)(C:\Users\Peggy\AppData\Roaming\Typora\typora-user-images\image-20220826194634780.png)]

image-20220826195457314

这个是由于我们JSON在解析 **LocalDateTime**格式的数据时没有对于的序列化规则,所以采用的默认的序列化的规则,返回了一堆数组。解决的方式就是配置一个序列化的规则让其执行

当然其实也可以直接通过 **@JsonFormat(pattern = “yyyy年MM月dd日”)**的这种格式进行序列化

@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    fastJsonConfig.setSerializerFeatures(
            SerializerFeature.PrettyFormat,
            SerializerFeature.WriteMapNullValue,
            SerializerFeature.DisableCircularReferenceDetect
    );
    fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
    fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
    converters.add(0, fastJsonHttpMessageConverter);
}

SpringBoot+MyBatis-plus 瑞吉外卖项目 Day05_第4张图片

你可能感兴趣的:(java,Spring,mybatis,spring,boot,java)