Spring Boot中使用MyBatis-Plus与ThreadLocal自动填充公共字段

橘子海
橘子海
发布时间:2026-10-16| 6人浏览过
原创

在Spring Boot项目开发中,数据库表的审计字段(如创建人、创建时间、修改人、修改时间)通常需要在每次插入和更新时自动维护。传统的手动赋值方式不仅繁琐且易出错。本文介绍如何通过MyBatis-Plus提供的MetaObjectHandler接口实现公共字段的自动填充,并结合ThreadLocal技术在过滤器中获取当前登录用户ID,解决跨层动态传参的问题,从而实现全自动化的数据维护。

1. 公共字段自动填充功能实现

在业务系统中,员工表或各类管理表中通常包含 create_time、create_user、update_time 和 update_user 等公共字段。若在每个Service方法中手动调用setter进行赋值,将导致大量重复代码。

第1步:分析问题与确定策略

我们需要区分不同操作的赋值时机:createTime仅在插入时赋予当前时间;updateTime在插入和更新时均需赋予当前时间;而用户相关字段则依赖当前上下文中的登录用户信息。通过在实体类属性上配置 @TableField(fill = FieldFill.xxx) 注解,可以明确指定各字段的填充规则。

第2步:编写元数据对象处理器

实现MyBatis-Plus的 MetaObjectHandler 接口,重写 insertFill 和 updateFill 方法,统一处理字段逻辑。此组件由Spring容器管理,拦截器会在执行SQL前自动调用。

首先,确保实体类正确映射字段:

@Data
public class Employee implements Serializable {
    private Long id;
    // ... 其他字段

    @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;
}

接着,编写处理器类:

@Component
@Slf4j
public class MyMetaObjecthandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("开始插入填充...");
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
        this.strictInsertFill(metaObject, "createUser", Long.class, BaseContext.getCurrentId());
        this.strictInsertFill(metaObject, "updateUser", Long.class, BaseContext.getCurrentId());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("开始更新填充...");
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
        this.strictUpdateFill(metaObject, "updateUser", Long.class, BaseContext.getCurrentId());
    }
}

2. 使用ThreadLocal动态获取当前登录用户

上述代码中调用了 BaseContext.getCurrentId()。在Controller和Service中,我们通常能通过Security Context或Session获取用户信息,但在底层持久层的 MetaObjectHandler 中无法直接访问HTTP会话对象。因此,需要一种跨层传递数据的机制。

第3步:理解ThreadLocal的作用

ThreadLocal 为每个线程提供独立的变量副本。在一次完整的HTTP请求生命周期内,服务端分配的线程是固定的。通过将该线程对应的用户ID存入 ThreadLocal,后续的DAO层或工具类均可通过该线程安全地获取同一份数据。

第4步:封装BaseContext工具类

创建一个静态内部持有 ThreadLocal 的工具类,提供设置和获取当前用户ID的方法:

public class BaseContext {
    public static ThreadLocal threadLocal = new ThreadLocal<>();

    public static void setCurrentId(Long id) {
        threadLocal.set(id);
    }

    public static Long getCurrentId() {
        return threadLocal.get();
    }
}

第5步:在过滤器中注入用户ID

在拦截未登录请求的 LoginCheckFilter 中,如果校验通过(用户已登录),则在放行前从 Session 取出用户ID并存入 ThreadLocal:

// LoginCheckFilter 片段
if (request.getSession().getAttribute("employee") != null) {
    // 1. 获取登录用户ID
    Long empId = (Long) request.getSession().getAttribute("employee");
    // 2. 存入ThreadLocal供后续层使用
    BaseContext.setCurrentId(empId);
    
    // 放行继续执行
    filterChain.doFilter(request, response);
    return;
}
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));

3. 验证与测试

完成配置后,可删除业务逻辑中关于时间戳和用户ID的手动赋值代码。启动项目,通过前端界面执行新增或修改操作。

最后查询数据库,观察 CREATE_TIME、UPDATE_TIME 以及关联的用户ID是否被正确填充。如果一切正常,说明 MetaObjectHandler 与 ThreadLocal 的协作已成功建立,实现了全链路自动化维护。

以上就是Springboot公共字段填充及ThreadLocal模块改进方案的详细内容,更多关于Springboot 公共字段填充的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。