Răsfoiți Sursa

feat:更换切换数据源逻辑,脏数据条不回传前端异常信息

韩帛霖 1 an în urmă
părinte
comite
4568f6ee77

+ 52 - 4
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/SqlInterceptor.java

@@ -25,24 +25,72 @@ public class SqlInterceptor implements Interceptor {
     public Object intercept(Invocation invocation) throws Throwable, TenantDataSource {
         StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
         String sql = statementHandler.getBoundSql().getSql();
-        // 修改SQL语句
-        String modifiedSql = BeforeSQL(sql);
+        // SQL执行前
+        // String modifiedSql = BeforeSQL(sql);
+        // 拼接sql
+        String modifiedSql = modifySql(sql);
+
+
         if (modifiedSql.equals("error")) {
             // 终止程序
             return AjaxResult.error("当前用户没有数据源信息!");
         } else {
+            // 将修改后的SQL语句设置回StatementHandler
+//            ReflectUtils.setFieldValue(statementHandler.getBoundSql(), "sql", modifiedSql);
+//            invocation.proceed();
+//            ReflectUtils.setFieldValue(statementHandler.getBoundSql(), "sql", sql);
+//            return invocation.proceed();
+
+
             // 将修改后的SQL语句设置回StatementHandler
             ReflectUtils.setFieldValue(statementHandler.getBoundSql(), "sql", modifiedSql);
-            invocation.proceed();
-            ReflectUtils.setFieldValue(statementHandler.getBoundSql(), "sql", sql);
             return invocation.proceed();
         }
     }
 
+    // 根据类型设置不同的选择数据源格式
+    private String modifySql(String sql) {
+        try {
+            SecurityUtils.getDatabaseType();
+        } catch (Exception e) {
+            return "error";
+        }
+        if (SecurityUtils.getDatabaseType().equals("sqlserver"))
+            return "USE `" + SecurityUtils.getDatabaseName() + "`; " + sql;
+        if (SecurityUtils.getDatabaseType().equals("dm"))
+            return "set schema " + SecurityUtils.getDatabaseName() + "; " + sql;
+        if (SecurityUtils.getDatabaseType().equals("mysql")) {
+            if (sql.contains("{DBNAME}.")) {
+                return sql.replace("{DBNAME}.", "`" + SecurityUtils.getDatabaseName() + "`.");
+            } else {
+                if (sql.contains("information_schema")) return sql;  // 执行当前sql不需要选择数据源
+                StringBuilder sb = new StringBuilder(sql);
+                int index = sb.indexOf(" from ");
+                if (index != -1) {
+                    sb.insert(index + 6, "`" + SecurityUtils.getDatabaseName() + "`.");  // 在目标字符后插入新的字符串
+                } else {
+                    index = sb.indexOf(" FROM ");
+                    if (index != -1)
+                        sb.insert(index + 6, "`" + SecurityUtils.getDatabaseName() + "`.");  // 在目标字符后插入新的字符串
+                }
+                return sb.toString();
+            }
+        }
+        return "error";
+    }
+
+    // 根据类型设置不同的选择数据源格式
     private String BeforeSQL(String sql) {
         try {
             SecurityUtils.getDatabaseType();
         } catch (Exception e) {
+            /**
+             * 如何当前请求中并不携带该用户的数据源信息
+             * 分两种情况:
+             * 1.当前用户并没有数据源信息(例如:admin并没有从库数据源信息)
+             * 2.当前用户的token失效(理论上在客户端发送请求时会携带token,逻辑代码执行前会首先验证token的有效性)
+             * 几乎不会出现第二种情况
+             */
             return "error";
         }
         if (SecurityUtils.getDatabaseType().equals("sqlserver"))

+ 45 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/SqlLogAspect.java

@@ -0,0 +1,45 @@
+package com.ruoyi.framework.aspectj;
+
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+@Aspect
+@Component
+public class SqlLogAspect {
+
+    @Around("execution(* com.zkqy.datamodeling.mapper.*.*(..))") // 匹配所有Mapper接口的方法
+    public Object logSql(ProceedingJoinPoint joinPoint) throws Throwable {
+        // 获取目标对象、方法和参数
+        Object target = joinPoint.getTarget();
+        String methodName = joinPoint.getSignature().getName();
+        Object[] args = joinPoint.getArgs();
+        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+        Class<?> returnType = signature.getReturnType();
+
+        // 执行目标方法
+        Object result = joinPoint.proceed();
+
+        // 判断结果集类型
+        if (result instanceof List) {
+            List<?> list = (List<?>) result;
+            for (Object item : list) {
+                // 遍历结果集中的每一行数据,打印相关信息
+                Field[] fields = item.getClass().getDeclaredFields();
+                for (Field field : fields) {
+                    field.setAccessible(true);
+                    System.out.println(field.getName() + ": " + field.get(item));
+                }
+            }
+        } else {
+            return Class.forName(returnType.toString().split("class ")[1]).newInstance();
+        }
+
+        return result;
+    }
+}