问题说明
原本数据权限的忽略方案是每次在查询之前去查找当前类上或者方法上是否有忽略注解的权限,优化之后每次项目启动时将所有配置了忽略数据权限注解的类加载到ConcurrentHashMap中,在有查询过来是直接去缓存中读取
/**
* 方法或类(名称) 与 注解的映射关系缓存
*/
private final Map<String, DataPermission> dataPermissionCacheMap = new ConcurrentHashMap<>();
原本方案
mappedStatementId
存储的是mapper的类路径,再通过反射去找类上和方法上注解是否忽略
运行时调用方法
查找是否存在忽略注解
改进后方案
通过yml配置的包路径,在项目启动时注入扫描
/**
* 通过 mapperPackage 设置的扫描包 扫描缓存有注解的方法与类
*/
private void scanMapperClasses(String mapperPackage) {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
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);
Resource[] resources = resolver.getResources(classpath + path + "/*.class");
for (Resource resource : resources) {
ClassMetadata classMetadata = factory.getMetadataReader(resource).getClassMetadata();
Class<?> clazz = Resources.classForName(classMetadata.getClassName());
findAnnotation(clazz);
}
}
} catch (Exception e) {
log.error("初始化数据安全缓存时出错:{}", e.getMessage());
}
}
扫描完添加到缓存中
private void findAnnotation(Class<?> clazz) {
DataPermission dataPermission;
// 获取方法注解
for (Method method : clazz.getMethods()) {
if (method.isDefault() || method.isVarArgs()) {
continue;
}
String mappedStatementId = clazz.getName() + "." + method.getName();
if (AnnotationUtil.hasAnnotation(method, DataPermission.class)) {
dataPermission = AnnotationUtil.getAnnotation(method, DataPermission.class);
dataPermissionCacheMap.put(mappedStatementId, dataPermission);
}
}
// 获取类注解
if (AnnotationUtil.hasAnnotation(clazz, DataPermission.class)) {
dataPermission = AnnotationUtil.getAnnotation(clazz, DataPermission.class);
dataPermissionCacheMap.put(clazz.getName(), dataPermission);
}
}
这样每次查询过来时调用此方法即可
public DataPermission getDataPermission(String mapperId) {
if (dataPermissionCacheMap.containsKey(mapperId)) {
return dataPermissionCacheMap.get(mapperId);
}
String clazzName = mapperId.substring(0, mapperId.lastIndexOf("."));
if (dataPermissionCacheMap.containsKey(clazzName)) {
return dataPermissionCacheMap.get(clazzName);
}
return null;
}