mirror of
				https://github.com/dromara/RuoYi-Vue-Plus.git
				synced 2025-11-04 08:13:44 +08:00 
			
		
		
		
	fix 修复 aop 无法拦截mapper接口上的注解导致的问题 类上依旧使用扫描处理
This commit is contained in:
		@@ -52,7 +52,7 @@ public class MybatisPlusConfig {
 | 
			
		||||
     * 数据权限拦截器
 | 
			
		||||
     */
 | 
			
		||||
    public PlusDataPermissionInterceptor dataPermissionInterceptor() {
 | 
			
		||||
        return new PlusDataPermissionInterceptor();
 | 
			
		||||
        return new PlusDataPermissionInterceptor(SpringUtils.getProperty("mybatis-plus.mapperPackage"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package org.dromara.common.mybatis.handler;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.annotation.AnnotationUtil;
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
@@ -8,6 +9,7 @@ import net.sf.jsqlparser.expression.Expression;
 | 
			
		||||
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
 | 
			
		||||
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
 | 
			
		||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
 | 
			
		||||
import org.apache.ibatis.io.Resources;
 | 
			
		||||
import org.dromara.common.core.domain.dto.RoleDTO;
 | 
			
		||||
import org.dromara.common.core.domain.model.LoginUser;
 | 
			
		||||
import org.dromara.common.core.exception.ServiceException;
 | 
			
		||||
@@ -19,17 +21,26 @@ import org.dromara.common.mybatis.annotation.DataPermission;
 | 
			
		||||
import org.dromara.common.mybatis.enums.DataScopeType;
 | 
			
		||||
import org.dromara.common.mybatis.helper.DataPermissionHelper;
 | 
			
		||||
import org.dromara.common.satoken.utils.LoginHelper;
 | 
			
		||||
import org.springframework.context.ConfigurableApplicationContext;
 | 
			
		||||
import org.springframework.context.expression.BeanFactoryResolver;
 | 
			
		||||
import org.springframework.core.io.Resource;
 | 
			
		||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 | 
			
		||||
import org.springframework.core.io.support.ResourcePatternResolver;
 | 
			
		||||
import org.springframework.core.type.ClassMetadata;
 | 
			
		||||
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
 | 
			
		||||
import org.springframework.expression.BeanResolver;
 | 
			
		||||
import org.springframework.expression.ExpressionParser;
 | 
			
		||||
import org.springframework.expression.ParserContext;
 | 
			
		||||
import org.springframework.expression.common.TemplateParserContext;
 | 
			
		||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
 | 
			
		||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
 | 
			
		||||
import org.springframework.util.ClassUtils;
 | 
			
		||||
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
import java.util.function.Function;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -41,6 +52,11 @@ import java.util.function.Function;
 | 
			
		||||
@Slf4j
 | 
			
		||||
public class PlusDataPermissionHandler {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 类名称与注解的映射关系缓存(由于aop无法拦截mybatis接口类上的注解 只能通过启动预扫描的方式进行)
 | 
			
		||||
     */
 | 
			
		||||
    private final Map<String, DataPermission> dataPermissionCacheMap = new ConcurrentHashMap<>();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * spel 解析器
 | 
			
		||||
     */
 | 
			
		||||
@@ -51,6 +67,15 @@ public class PlusDataPermissionHandler {
 | 
			
		||||
     */
 | 
			
		||||
    private final BeanResolver beanResolver = new BeanFactoryResolver(SpringUtils.getBeanFactory());
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 构造方法,扫描指定包下的 Mapper 类并初始化缓存
 | 
			
		||||
     *
 | 
			
		||||
     * @param mapperPackage Mapper 类所在的包路径
 | 
			
		||||
     */
 | 
			
		||||
    public PlusDataPermissionHandler(String mapperPackage) {
 | 
			
		||||
        scanMapperClasses(mapperPackage);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获取数据过滤条件的 SQL 片段
 | 
			
		||||
     *
 | 
			
		||||
@@ -62,7 +87,7 @@ public class PlusDataPermissionHandler {
 | 
			
		||||
    public Expression getSqlSegment(Expression where, String mappedStatementId, boolean isSelect) {
 | 
			
		||||
        try {
 | 
			
		||||
            // 获取数据权限配置
 | 
			
		||||
            DataPermission dataPermission = DataPermissionHelper.getPermission();
 | 
			
		||||
            DataPermission dataPermission = getDataPermission(mappedStatementId);
 | 
			
		||||
            // 获取当前登录用户信息
 | 
			
		||||
            LoginUser currentUser = DataPermissionHelper.getVariable("user");
 | 
			
		||||
            if (ObjectUtil.isNull(currentUser)) {
 | 
			
		||||
@@ -169,12 +194,68 @@ public class PlusDataPermissionHandler {
 | 
			
		||||
        return "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 扫描指定包下的 Mapper 类,并查找其中带有特定注解的方法或类
 | 
			
		||||
     *
 | 
			
		||||
     * @param mapperPackage Mapper 类所在的包路径
 | 
			
		||||
     */
 | 
			
		||||
    private void scanMapperClasses(String mapperPackage) {
 | 
			
		||||
        // 创建资源解析器和元数据读取工厂
 | 
			
		||||
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
 | 
			
		||||
        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
 | 
			
		||||
        // 将 Mapper 包路径按分隔符拆分为数组
 | 
			
		||||
        String[] packagePatternArray = StringUtils.splitPreserveAllTokens(mapperPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
 | 
			
		||||
        String classpath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX;
 | 
			
		||||
        try {
 | 
			
		||||
            for (String packagePattern : packagePatternArray) {
 | 
			
		||||
                // 将包路径转换为资源路径
 | 
			
		||||
                String path = ClassUtils.convertClassNameToResourcePath(packagePattern);
 | 
			
		||||
                // 获取指定路径下的所有 .class 文件资源
 | 
			
		||||
                Resource[] resources = resolver.getResources(classpath + path + "/*.class");
 | 
			
		||||
                for (Resource resource : resources) {
 | 
			
		||||
                    // 获取资源的类元数据
 | 
			
		||||
                    ClassMetadata classMetadata = factory.getMetadataReader(resource).getClassMetadata();
 | 
			
		||||
                    // 获取资源对应的类对象
 | 
			
		||||
                    Class<?> clazz = Resources.classForName(classMetadata.getClassName());
 | 
			
		||||
                    // 查找类中的特定注解
 | 
			
		||||
                    if (AnnotationUtil.hasAnnotation(clazz, DataPermission.class)) {
 | 
			
		||||
                        DataPermission dataPermission = AnnotationUtil.getAnnotation(clazz, DataPermission.class);
 | 
			
		||||
                        dataPermissionCacheMap.put(clazz.getName(), dataPermission);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            log.error("初始化数据安全缓存时出错:{}", e.getMessage());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 根据映射语句 ID 或类名获取对应的 DataPermission 注解对象
 | 
			
		||||
     *
 | 
			
		||||
     * @param mapperId 映射语句 ID
 | 
			
		||||
     * @return DataPermission 注解对象,如果不存在则返回 null
 | 
			
		||||
     */
 | 
			
		||||
    public DataPermission getDataPermission(String mapperId) {
 | 
			
		||||
        // 检查上下文中是否包含映射语句 ID 对应的 DataPermission 注解对象
 | 
			
		||||
        if (DataPermissionHelper.getPermission() != null) {
 | 
			
		||||
            return DataPermissionHelper.getPermission();
 | 
			
		||||
        }
 | 
			
		||||
        // 如果缓存中不包含映射语句 ID 对应的 DataPermission 注解对象,则尝试使用类名作为键查找
 | 
			
		||||
        String clazzName = mapperId.substring(0, mapperId.lastIndexOf("."));
 | 
			
		||||
        if (dataPermissionCacheMap.containsKey(clazzName)) {
 | 
			
		||||
            return dataPermissionCacheMap.get(clazzName);
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 检查给定的映射语句 ID 是否有效,即是否能够找到对应的 DataPermission 注解对象
 | 
			
		||||
     *
 | 
			
		||||
     * @param mapperId 映射语句 ID
 | 
			
		||||
     * @return 如果找到对应的 DataPermission 注解对象,则返回 false;否则返回 true
 | 
			
		||||
     */
 | 
			
		||||
    public boolean invalid() {
 | 
			
		||||
        return DataPermissionHelper.getPermission() == null;
 | 
			
		||||
    public boolean invalid(String mapperId) {
 | 
			
		||||
        return getDataPermission(mapperId) == null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -39,9 +39,11 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 构造函数,初始化 PlusDataPermissionHandler 实例
 | 
			
		||||
     *
 | 
			
		||||
     * @param mapperPackage 扫描的映射器包
 | 
			
		||||
     */
 | 
			
		||||
    public PlusDataPermissionInterceptor() {
 | 
			
		||||
        this.dataPermissionHandler = new PlusDataPermissionHandler();
 | 
			
		||||
    public PlusDataPermissionInterceptor(String mapperPackage) {
 | 
			
		||||
        this.dataPermissionHandler = new PlusDataPermissionHandler(mapperPackage);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -62,7 +64,7 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // 检查是否缺少有效的数据权限注解
 | 
			
		||||
        if (dataPermissionHandler.invalid()) {
 | 
			
		||||
        if (dataPermissionHandler.invalid(ms.getId())) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // 解析 sql 分配对应方法
 | 
			
		||||
@@ -90,7 +92,7 @@ public class PlusDataPermissionInterceptor extends BaseMultiTableInnerIntercepto
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            // 检查是否缺少有效的数据权限注解
 | 
			
		||||
            if (dataPermissionHandler.invalid()) {
 | 
			
		||||
            if (dataPermissionHandler.invalid(ms.getId())) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user