mybatis-plus实现自动填充创建人/更新人以及时间字段

1.通用实体类

package com.sundark.mylife.entity;


import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.time.LocalDateTime;


/**
 * @author wwujiada
 */
@Data
@Accessors(chain = true)
public class BaseDO implements Serializable {

    // 主键
    @TableId(type = IdType.AUTO)
    private Integer id;

    /**
     * 创建时间
     */
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    /**
     * 创建人id
     */
    @TableField(value = "creator", fill = FieldFill.INSERT)
    private Integer creator;

    /**
     * 更新时间
     */
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;

    /**
     * 更新人id
     */
    @TableField(value = "updater", fill = FieldFill.INSERT_UPDATE)
    private Integer updater;

    // 逻辑删除字段,MyBatis-Plus 3.x 默认使用 LogicDelete 注解,并识别字段名为 deleted 或 is_deleted
    @TableLogic
    private Boolean deleted;

}

2.TreadLocal类

package com.sundark.mylife.utils;

/**
 * @author wujiada
 * 线程私有对象
 */
public class ThreadLocalUtil {

    private final static ThreadLocal USER_THREAD_LOCAL = new ThreadLocal<>();

    /**
     * 设置数据到当前线程
     */
    public static void set(Object o) {
        USER_THREAD_LOCAL.set(o);
    }

    /**
     * 获取线程中的数据
     */
    public static Object get() {
        return USER_THREAD_LOCAL.get();
    }

    /**
     * 删除线程中的数据
     */
    public static void remove() {
        USER_THREAD_LOCAL.remove();
    }
}

3.mybatis-plus配置类,从TreadLocal中取出用户信息

package com.sundark.mylife.config;


import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.sundark.mylife.constants.SysConstant;
import com.sundark.mylife.entity.BaseDO;
import com.sundark.mylife.entity.model.MlUserDO;
import com.sundark.mylife.enums.CodeEnum;
import com.sundark.mylife.exception.ServiceException;
import com.sundark.mylife.utils.ThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;
import java.util.Objects;

/**
 * @author wujiada
 * mybatis-plus自动填充字段配置
 */
@Configuration
@Slf4j
public class MybatisPlusConfig {

    /**
     * 自动填充创建者、更新者等字段
     *
     * @return 自定义的 MetaObjectHandler
     */
    @Bean
    public MetaObjectHandler metaObjectHandler() {
        return new MetaObjectHandler() {

            @Override
            public void insertFill(MetaObject metaObject) {
                if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO baseDO) {
                    LocalDateTime current = LocalDateTime.now();
                    // 创建时间为空,则以当前时间为插入时间
                    if (Objects.isNull(baseDO.getCreateTime())) {
                        baseDO.setCreateTime(current);
                    }
                    // 更新时间为空,则以当前时间为更新时间
                    if (Objects.isNull(baseDO.getUpdateTime())) {
                        baseDO.setUpdateTime(current);
                    }
                    // ThreadLocal中获取用户id
                    MlUserDO userDO = (MlUserDO) ThreadLocalUtil.get();
                    Integer userId;
                    // 注册的时候没有用户id,默认使用系统用户id
                    if (userDO != null) {
                        userId = userDO.getId();
                    } else {
                        userId = SysConstant.ADMIN_ID;
                    }

                    // 当前登录用户不为空,创建人为空,则当前登录用户为创建人
                    if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) {
                        baseDO.setCreator(userId);
                    }
                    // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
                    if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) {
                        baseDO.setUpdater(userId);
                    }

                    // 当前删除flag为null
                    if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) {
                        baseDO.setUpdater(userId);
                    }
                }
            }

            @Override
            public void updateFill(MetaObject metaObject) {
                // 更新时间为空,则以当前时间为更新时间
                Object modifyTime = getFieldValByName("updateTime", metaObject);
                if (Objects.isNull(modifyTime)) {
                    setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
                }

                // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
                Object modifier = getFieldValByName("updater", metaObject);
                // ThreadLocal中获取用户id
                MlUserDO userDO = (MlUserDO) ThreadLocalUtil.get();
                // 更新说明该用户登录了
                if (userDO == null) {
                    throw new ServiceException(CodeEnum.USER_NOT_EXISTS);
                }
                Integer userId = userDO.getId();
                if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
                    setFieldValByName("updater", userId, metaObject);
                }
            }
        };
    }
}

4.鉴权过滤器,将用户信息存储到TreadLocal中

package com.sundark.mylife.filter;

import com.sundark.mylife.constants.SysConstant;
import com.sundark.mylife.entity.model.MlUserDO;
import com.sundark.mylife.utils.StringUtil;
import com.sundark.mylife.utils.ThreadLocalUtil;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.io.IOException;

import static com.sundark.mylife.utils.JwtUtil.isValidToken;

/**
 * @author wujiada
 * 鉴权过滤器
 */
@Component
@Order(1)
@Slf4j// 数字越大,优先级越低
public class AuthFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    /**
     * 处理请求
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        // 假设登录请求的URL是/login
        // /user/api/v1/user/login 和/register
        String uri = httpRequest.getRequestURI();
        if (uri.contains("/doc.html") || uri.startsWith("/swagger-ui.html") || uri.startsWith("/v3/api-docs") || uri.startsWith("/swagger-resources/") ||
                uri.contains(SysConstant.LOGIN_URL) || uri.contains(SysConstant.REGISTER_URL)) {
            // 登录/注册请求,放行
            chain.doFilter(request, response);
        } else {
            // 对于非登录注册请求,进行鉴权
            String token = httpRequest.getHeader("token");
            String userId = isValidToken(token);
            if (StringUtil.isEmpty(userId)) {
                // 鉴权失败,返回未授权响应
                httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                httpResponse.getWriter().write("Unauthorized access");
                return;
            }
            // 登录用户存入ThreadLocal
            MlUserDO user = new MlUserDO();
            user.setId(Integer.valueOf(userId));
            ThreadLocalUtil.set(user);

            try {
                // 放行
                chain.doFilter(request, response);
            } finally {
                // 手动移除ThreadLocal内存数据,防止内存溢出
                ThreadLocalUtil.remove();
            }
        }
    }


    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

你可能感兴趣的:(Java,mybatis,java,mybatis-plus)