一、MybatisPlus公共字段自动填充
1.1、问题分析
在对数据表进行新增或修改时,都需要指定 创建人(createUser)、创建时间(createTime)、修改人(updateUser)、修改时间(updateTime) 等公共字段,那有没有办法让这些字段在一个地方统一管理呢?从而简化我们的开发,答案就是使用MybatisPlus给我们提供的公共字段自动填充功能
1.2、代码实现
1.2.1、在实体类的属性上方加入@TableFiled注解,指定自动填充的策略
// 员工实体类
@Data
public class Employee implements Serializable {
private String name;
private String password;
@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;
}
1.2.2、按照框架要求编写元数据对象处理器
定义 MyMetaObjectHandler 类,在此类中统一对公共字段赋值,此类需要实现MetaObjectHandler接口。实现接口之后,重写两个方法,一个是插入时填充,一个是修改时填充。关于字段填充方式,使用metaObject的setValue来实现。
// 自定义元数据对象处理器--createTime、updateTime、createUser、updateUser
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 插入insert时自动填充
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("createUser", BaseContext.getCurrentId());//同一线程取id
metaObject.setValue("updateUser", BaseContext.getCurrentId());//同一线程取id
}
/**
* 更新updata时自动填充
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("updateUser", BaseContext.getCurrentId());//同一线程取id
}
}
1.2.3、关于id的获取
请看下节:同一线程数据可传输
二、同一线程数据可传输
2.1、问题分析
关于id的获取,之前是存到session里的,但在MyMetaObjectHandler类中不能获得HttpSession对象,所以我们需要用其他方式来获取登录用户Id。由此引出:同一线程数据可传输
2.2、统一线程
-
在学习ThreadLocal之前,我们需要先确认一个事情,就是客户端发送的每次http请求,对应的在服务端都会分配一个新的线程来处理,在处理过程中涉及到下面类中的方法都属于相同的一个线程:
LocalCheekFilter中的doFilter方法EmployeeController中的update方法MyMetaObjectHandler中的updateFill方法
2.3、实现方法
可以在LoginCheckFilter的doFilter方法中获取当前登录用户id,并调用ThreadLocal的set方法来设置当前线程的线程局部变量的值(用户id),然后在MyMetaObjectHandler的updateFill方法中调用ThreadLocal的get方法来获得当前线程所对应的线程局部变量的值(用户id)。
2.4、具体实现
2.4.1、在com.blog.common包下新建BaseContext类,作用:基于ThreadLocal的封装工具类,用于保护和获取当前用户id(同一线程传递数据)set、get
public class BaseContext {
private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
public static void setCurrentId(Long id) {
threadLocal.set(id);
}
public static Long getCurrentId() {
return threadLocal.get();
}
}
2.4.2、随后在LoginCheckFilter类中添加代码,使用 request.getSession 来 存id(BaseContext.setICurrentId(empId))
//4、判断登录状态,如果已登录,则直接放行
if(request.getSession().getAttribute("employee") != null){
log.info("用户已登录,id为{}",request.getSession().getAttribute("employee"));
//同一线程存id
Long empId = (Long) request.getSession().getAttribute("employee");
BaseContext.setICurrentId(empId); //同一线程存id
filterChain.doFilter(request,response);
return;
}
2.4.3、在MyMetaObjectHandler类中,取id(BaseContext.getCurrentId())
// 自定义元数据对象处理器--createTime、updateTime、createUser、updateUser
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 插入insert时自动填充
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("createUser", BaseContext.getCurrentId());//同一线程取id
metaObject.setValue("updateUser", BaseContext.getCurrentId());//同一线程取id
}
/**
* 更新updata时自动填充
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("updateUser", BaseContext.getCurrentId());//同一线程取id
}
}