274 lines
10 KiB
Java
274 lines
10 KiB
Java
/*
|
||
* Copyright (c) 2018-2025, songfayuan All rights reserved.
|
||
*
|
||
* Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted provided that the following conditions are met:
|
||
*
|
||
* Redistributions of source code must retain the above copyright notice,
|
||
* this list of conditions and the following disclaimer.
|
||
* Redistributions in binary form must reproduce the above copyright
|
||
* notice, this list of conditions and the following disclaimer in the
|
||
* documentation and/or other materials provided with the distribution.
|
||
* Neither the name of the 霖梓控股 developer nor the names of its
|
||
* contributors may be used to endorse or promote products derived from
|
||
* this software without specific prior written permission.
|
||
* Author: songfayuan (1414798079@qq.com)
|
||
*/
|
||
|
||
package com.lz.config;
|
||
|
||
import cn.hutool.core.collection.CollectionUtil;
|
||
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
||
import com.baomidou.mybatisplus.extension.handlers.AbstractSqlParserHandler;
|
||
import com.lz.common.utils.OrderUtil;
|
||
import com.lz.common.utils.ReflectionUtils;
|
||
import com.lz.common.utils.SpringContextUtils;
|
||
import com.lz.common.utils.StringUtil;
|
||
import lombok.extern.slf4j.Slf4j;
|
||
import org.apache.ibatis.binding.BindingException;
|
||
import org.apache.ibatis.executor.statement.StatementHandler;
|
||
import org.apache.ibatis.mapping.BoundSql;
|
||
import org.apache.ibatis.mapping.MappedStatement;
|
||
import org.apache.ibatis.mapping.ParameterMapping;
|
||
import org.apache.ibatis.mapping.SqlCommandType;
|
||
import org.apache.ibatis.plugin.*;
|
||
import org.apache.ibatis.reflection.MetaObject;
|
||
import org.apache.ibatis.reflection.SystemMetaObject;
|
||
import org.apache.ibatis.session.Configuration;
|
||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||
import org.slf4j.LoggerFactory;
|
||
|
||
import java.sql.Connection;
|
||
import java.text.DateFormat;
|
||
import java.util.*;
|
||
|
||
/**
|
||
* @author songfayuan
|
||
* @date 2018/1/19
|
||
* 数据权限插件,guns
|
||
*/
|
||
@Slf4j
|
||
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
|
||
public class DataScopeInterceptor extends AbstractSqlParserHandler implements Interceptor {
|
||
|
||
public static final org.slf4j.Logger logger = LoggerFactory.getLogger(DataScopeInterceptor.class);
|
||
|
||
@Override
|
||
public Object intercept(Invocation invocation) throws Throwable {
|
||
StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
|
||
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
|
||
this.sqlParser(metaObject);
|
||
// 先判断是不是SELECT操作
|
||
BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
|
||
String originalSql = boundSql.getSql();
|
||
Object parameterObject = boundSql.getParameterObject();
|
||
MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
|
||
String mapperdId = getMapperId(mappedStatement);
|
||
String sqlCommandTypePre = "SELECT SQL = " + mapperdId + " ";
|
||
if(SqlCommandType.INSERT.equals(mappedStatement.getSqlCommandType())){
|
||
sqlCommandTypePre = "INSERT SQL = " + mapperdId + " ";
|
||
}else if (SqlCommandType.UPDATE.equals(mappedStatement.getSqlCommandType())){
|
||
sqlCommandTypePre = "UPDATE SQL = " + mapperdId + " ";
|
||
}
|
||
|
||
Configuration configuration = mappedStatement.getConfiguration();
|
||
if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) { //非select语句
|
||
if(SpringContextUtils.isSQLLogDebug()){
|
||
logger.info(sqlCommandTypePre + showSql(configuration, boundSql));
|
||
}
|
||
Object result = invocation.proceed();
|
||
return result ;
|
||
}
|
||
//查找参数中包含DataScope类型的参数
|
||
DataScope dataScope = findDataScopeObject(parameterObject);
|
||
if (dataScope == null) {
|
||
String sql = getContainsIsDeleteOriginalSql(originalSql);
|
||
if(SpringContextUtils.isSQLLogDebug()){
|
||
logger.info(sqlCommandTypePre + showSql(configuration, boundSql));
|
||
}
|
||
metaObject.setValue("delegate.boundSql.sql", sql);
|
||
Object result = invocation.proceed();
|
||
return result ;
|
||
} else {
|
||
String scopeName = dataScope.getScopeName();
|
||
List<Integer> deptIds = dataScope.getDeptIds();
|
||
if (StringUtil.isNotBlank(scopeName) && CollectionUtil.isNotEmpty(deptIds)) {
|
||
String join = CollectionUtil.join(deptIds, ",");
|
||
originalSql = "select * from (" + originalSql + ") temp_data_scope where temp_data_scope." + scopeName + " in (" + join + ")";
|
||
metaObject.setValue("delegate.boundSql.sql", originalSql);
|
||
}
|
||
|
||
if(SpringContextUtils.isSQLLogDebug()){
|
||
logger.info(sqlCommandTypePre + showSql(configuration, boundSql));
|
||
}
|
||
Object result=invocation.proceed();
|
||
return result;
|
||
}
|
||
}
|
||
|
||
// todo quyixiao 所有的sql查询加上is_delete=0,目前没有想到解决办法
|
||
public static String getContainsIsDeleteOriginalSql(String originalSql){
|
||
|
||
return originalSql;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
private static String getParameterValue(Object obj) {
|
||
String value = null;
|
||
if (obj instanceof String) {
|
||
value = "'" + obj.toString() + "'";
|
||
} else if (obj instanceof Date) {
|
||
DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
|
||
value = "'" + formatter.format(obj) + "'";
|
||
} else {
|
||
if (obj != null) {
|
||
value = obj.toString();
|
||
} else {
|
||
value = "''";
|
||
}
|
||
}
|
||
return value;
|
||
}
|
||
|
||
|
||
@SuppressWarnings("unused")
|
||
private static Object getParameterValue(String propertyName, Object obj) {
|
||
|
||
Object value = null;
|
||
|
||
try {
|
||
value = ReflectionUtils.getObjectFieldValue(obj, propertyName);
|
||
} catch (BindingException e2) {
|
||
return null;
|
||
}
|
||
return value;
|
||
}
|
||
|
||
/**
|
||
* 生成拦截对象的代理
|
||
*
|
||
* @param target 目标对象
|
||
* @return 代理对象
|
||
*/
|
||
@Override
|
||
public Object plugin(Object target) {
|
||
if (target instanceof StatementHandler) {
|
||
return Plugin.wrap(target, this);
|
||
}
|
||
return target;
|
||
}
|
||
|
||
/**
|
||
* mybatis配置的属性
|
||
*
|
||
* @param properties mybatis配置的属性
|
||
*/
|
||
@Override
|
||
public void setProperties(Properties properties) {
|
||
|
||
}
|
||
|
||
public static String getMapperId(MappedStatement mappedStatement) {
|
||
try {
|
||
String id = mappedStatement.getId();
|
||
if(id.contains(".")){
|
||
String ids []= id.split("\\.");
|
||
return ids[ids.length -2 ] +"."+ ids[ids.length -1 ];
|
||
}
|
||
return null;
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
} finally {
|
||
}
|
||
return "";
|
||
}
|
||
public static void main(String[] args) {
|
||
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* 查找参数是否包括DataScope对象
|
||
*
|
||
* @param parameterObj 参数列表
|
||
* @return DataScope
|
||
*/
|
||
private DataScope findDataScopeObject(Object parameterObj) {
|
||
if (parameterObj instanceof DataScope) {
|
||
return (DataScope) parameterObj;
|
||
} else if (parameterObj instanceof Map) {
|
||
for (Object val : ((Map<?, ?>) parameterObj).values()) {
|
||
if (val instanceof DataScope) {
|
||
return (DataScope) val;
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
|
||
|
||
public static String showSql(Configuration configuration, BoundSql boundSql) {
|
||
try {
|
||
Map<String,String> listMap = new HashMap<>();
|
||
Object parameterObject = boundSql.getParameterObject();
|
||
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
|
||
String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
|
||
if (parameterMappings.size() > 0 && parameterObject != null) {
|
||
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
|
||
if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
|
||
String value = getParameterValue(parameterObject);
|
||
if (value.contains("?")) {
|
||
String key = OrderUtil.getUserPoolOrder("rn");
|
||
listMap.put(key,value);
|
||
value = key;
|
||
}
|
||
sql = sql.replaceFirst("\\?", value);
|
||
} else {
|
||
MetaObject metaObject = configuration.newMetaObject(parameterObject);
|
||
for (ParameterMapping parameterMapping : parameterMappings) {
|
||
String propertyName = parameterMapping.getProperty();
|
||
if (metaObject.hasGetter(propertyName)) {
|
||
Object obj = metaObject.getValue(propertyName);
|
||
String value = getParameterValue(obj);
|
||
if (value.contains("?")) {
|
||
String key = OrderUtil.getUserPoolOrder("rn");
|
||
listMap.put(key,value);
|
||
value = key;
|
||
}
|
||
sql = sql.replaceFirst("\\?", value);
|
||
} else if (boundSql.hasAdditionalParameter(propertyName)) {
|
||
Object obj = boundSql.getAdditionalParameter(propertyName);
|
||
|
||
String value = getParameterValue(obj);
|
||
if (value.contains("?")) {
|
||
String key = OrderUtil.getUserPoolOrder("rn");
|
||
listMap.put(key,value);
|
||
value = key;
|
||
}
|
||
sql = sql.replaceFirst("\\?", value);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if(!listMap.isEmpty()){
|
||
for (Map.Entry<String, String> m : listMap.entrySet()) {
|
||
sql = sql.replaceAll(m.getKey(),m.getValue());
|
||
}
|
||
}
|
||
return sql;
|
||
} catch (Exception e) {
|
||
log.error("showSql exception ", e);
|
||
}
|
||
return "";
|
||
}
|
||
|
||
|
||
|
||
|
||
}
|