mysql-plus 动态修改全局sql, 进行数据隔离, 多租户, 多字段修改

需求:

1, 不同的权限角色看见的数据不一样, 进行数据隔离

2, 大部分表里面都维护了一个sys_code 大区编号,   1 是湖南, 2 是广东, 他们需要看到数据是不一样的

3, 不需要每个查询都自己去判断角色去修改sql,   可以配置多个字段, sys_code 隔离,  city_id 隔离, 省管理, 和市管理, 灵活配置

package com.test.first;

import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.core.parser.ISqlParserFilter;
import com.baomidou.mybatisplus.core.parser.SqlParserHelper;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.reflection.MetaObject;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.*;

@Configuration
@MapperScan(basePackages = {"com.dao"})
public class FilterConfig {
    private static final Map<String, String > IGNORE_TENANT_SMAP = new HashMap<String, String>(){{
        // 这些mapper 方法也不修改
        put("com.test.first.dao.TestMapper.getId","");
        put("com.test.first.dao.TestMapper.getId2","");
        put("com.test.first.dao.TestMapper.getId3","");
    }};

    private static final HashSet<String> TABLE_FILTER = new HashSet();

    static {
        // 过滤表, 这些表不进行修改
        TABLE_FILTER.add("sys_user");
        TABLE_FILTER.add("sys_user1");
        TABLE_FILTER.add("sys_user2");
    }

    @Autowired//自动注入request
    private HttpServletRequest request;

    @Bean
    @SuppressWarnings("all")
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

        // sql 解析器
        List<ISqlParser> sqlParserList = new ArrayList<>();
        TenantSqlParser tenantSqlParser = new TenantSqlParser();
        tenantSqlParser.setTenantHandler(new TenantHandler() {
            @Override
            public Expression getTenantId() {
                HttpSession session = request.getSession();
                // 此处返回sys_code 字段值, 修改sql时候的参数, 从session 里面获取用户,
                // 或者其他方式获取用户标识, 这里方便直接写死了
                return new LongValue(11);
            }
            @Override
            public String getTenantIdColumn() {
                // 返回增加条件的字段
                return "sys_code";
            }

            @Override
            public boolean doTableFilter(String tableName) {
                // 这里可以判断是否过滤表
                // 对没有sys_code 的表格进行过滤
                if (TABLE_FILTER.contains(tableName)){
                    // 返回true 则不过滤
                    return true;
                }
                return false;
            }
        });


        // 添加到解析器, 如需添加多个, 这个地方是list, 多new几个, new TenantSqlParser(); 即可
        sqlParserList.add(tenantSqlParser);

        // 设置解析器集合
        paginationInterceptor.setSqlParserList(sqlParserList);

        // 过滤函数
        paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {
            @Override
            public boolean doFilter(MetaObject metaObject) {
                MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject);
                // com.test.first.dao.TestMapper.getId 精确到mapper 方法级
                if(IGNORE_TENANT_SMAP.containsKey(ms.getId())) {
                    // 不进行修改
                    return true;
                }
                return false;
            }
        });
        return paginationInterceptor;
    }
}

原始sql

SELECT * FROM bd_product

经过配置后会自动增加条件

SELECT * FROM bd_product WHERE sys_code = 11

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章