springboot+mybatis拦截器

本文介绍了如何在SpringBoot结合Mybatis的项目中,利用拦截器实现根据机构标识过滤数据的需求。首先遇到拦截器不生效的问题,然后通过在SqlSessionFactory中添加拦截器解决了问题。同时,创建了自定义注解@PlatformTag和@PlatformTagIgnore,用于标记需要拦截或忽略的Mapper类和方法,使得代码更加灵活。
摘要由CSDN通过智能技术生成

项目需求,需要每个表添加一个机构标识, 由于来的分表合并为一个表中,通过机构标识来过滤数据。一个一个加太繁琐,所以使有了mybatis的拦截器。
先来说一下拦截器不生效的问题。开始想使用@component注解来注入拦截器,谁成想,拦截器确不生效。后来发现可能跟我的多数据源有问题。后来使用两个方法可解决,如有以下拦截器:

package com.zm.config;

import com.alibaba.nacos.common.utils.StringUtils;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.schema.Column;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.FromItem;
import net.sf.jsqlparser.statement.select.Join;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.util.deparser.ExpressionDeParser;
import net.sf.jsqlparser.statement.insert.Insert;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.*;

@Slf4j
@Intercepts({
   @Signature(type = StatementHandler.class, method = "prepare", args = {
   Connection.class, Integer.class})})
@Component
public class SqlInterceptor implements Interceptor {
   
    private static final String  COLUMN_NAME = "org_id";
    // 表别名
    private String tableAlias;

    @Value("${his.org}")
    private String orgId;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
   

        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        //通过MetaObject优雅访问对象的属性,这里是访问statementHandler的属性;:MetaObject是Mybatis提供的一个用于方便、
        //优雅访问对象属性的对象,通过它可以简化代码、不需要try/catch各种reflect异常,同时它支持对JavaBean、Collection、Map三种类型对象的操作。
        MetaObject metaObject = MetaObject
                .forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,
                        new DefaultReflectorFactory());
        //先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,其实现类是BaseStatementHandler,然后就到BaseStatementHandler的成员变量mappedStatement
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        //id为执行的mapper方法的全路径名,如com.uv.dao.UserMapper.insertUser
        String id = mappedStatement.getId();
        //sql语句类型 select、delete、insert、update
        String sqlCommandType = mappedStatement.getSqlCommandType().toString();
        //数据库连接信息
//        Configuration configuration = mappedStatement.getConfiguration();
//        ComboPooledDataSource dataSource = (ComboPooledDataSource)configuration.getEnvironment().getDataSource();
//        dataSource.getJdbcUrl();
        String sql2Reset="";
        if(SqlCommandType.SELECT.name().equals(sqlCommandType)){
   
            Select selectStatement = (Select) CCJSqlParserUtil.parse(statementHandler.getBoundSql().getSql());
            PlainSelect plain = (PlainSelect) selectStatement.getSelectBody();
            FromItem fromItem = plain.getFromItem();
            // 仅对枚举符合表, 并没有代理商字段的进行拼接sql
            Table table = this.ifConform(plain);
            if (table != null && this.doesItExist(plain.getWhere())) {
   
                // 进行拼接, 判断是否有where
                Expression where = plain.getWhere();
                // 获取查询语句表别名(兼容之前做好功能一个方法表别名不一致)
                String sqlTableAlias = table.getAlias() != null 
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值