MP 公共字段填充

MybatisPlus

公共字段填充

​ 统一为公共字段进行处理,在插入或更新时为指定字段赋予指定的值,减少了重复代码。公共字段一般为创建/更新时间,创建/更新人。可以通过LocalDateTime.now()来对创建/更新时间进行赋值,而创建/更新人可以通过 ThreadLocal 来赋值。ThreadLocal 是 JDK 中提供的一个类。

实现步骤:

  1. 实体类属性加入@TableFiled注解,指定自动填充策略
  2. 框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,该类需要实现MetaObjectHandler接口
@Data
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    @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;
}


@Slf4j
@Component
public class MyMetaObjectHandler 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]");
        long id = Thread.currentThread().getId();
        log.info("元数据处理的线程id:{}", id);
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", new Long("1L"));
    }
}

如何获取用户id?

MyMetaObjectHandle'类中是不能获得HttpSession对象,因此不能在MyMetaObjectHandler通过HttpSession来获取用户id。可以通过ThreadLocal类来获取用户id

什么是ThreadLocal?

  • ThreadLocal 类用来提供线程内部的局部变量,不同的线程之间的局部变量不会相互干扰
  • 在多线程环境下访问(通过 get 和 set 方法访问)时能保证各个线程的变量相对独立于其他线程内的变量 ThreadLocal 为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
常用方法 作用
public T get() 获取当前线程绑定的局部变量
public void set( T value) 设置当前线程绑定的局部变量

为什么可以使用ThreadLocal?

客户端每次发送请求,对应的服务端都会分配一个新的线程来处理。同一个请求响应链中涉及的方法都属于同一个线程。可以在调用链中使用如下方法来确认此事:

long id = Thread.currendThread().getId;
log.info("线程id:{}",id);

设置公共字段填充中的用户id字段

​ 将设置 id,获取 id 的方法封装为一个工具类

public class UserIdContext {
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    /**
     * 为当前线程设置id
     * @param id
     */
    public static void setCurrentId(Long id){
        threadLocal.set(id);
    }

    /**
     * 获取当前线程中的id
     * @return
     */
    public static Long getCurrentId(){
        return threadLocal.get();
    }
}

​ 通过 ThreadLocal 的 set 方法设置当前线程的线程局部变量的值,在元数据对象处理类中的方法调用 Thread 的 get 方法来获取当前线程所对应的线程局部变量的值。

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("元数据处理[insert]");
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("createUser", UserIdContext.getCurrentId());
        metaObject.setValue("updateUser", UserIdContext.getCurrentId());
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("元数据处理[update]");
        long id = Thread.currentThread().getId();
        log.info("元数据处理的线程id:{}", id);
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", UserIdContext.getCurrentId());
    }
}

问:户登录成功后我们将用户 id 存入了 HttpSession 中,MyMetaObjectHandler 类中是不能获得 HttpSession 对象,为什么?

posted @ 2023-01-16 16:25  九落  阅读(133)  评论(0)    收藏  举报