Browse Source

逻辑删除自动拼接更新用户和跟新时间

24282 1 year ago
parent
commit
7f6f05d8fc

+ 30 - 42
ruoyi-admin/src/main/resources/application-dev.yml

@@ -1,46 +1,34 @@
 # 数据源配置
 spring:
-    datasource:
-        dynamic:
-            strict: true
-            primary: base
-            datasource:
-                item:
-                    url: jdbc:mysql://36.134.91.96:17330/bytesailing_item?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: fjhx2012mysql
-                    password: 3PN-Mzn#vnP&q6d
-                supply:
-                    url: jdbc:mysql://36.134.91.96:17330/bytesailing_supply?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: fjhx2012mysql
-                    password: 3PN-Mzn#vnP&q6d
-                base:
-                    url: jdbc:mysql://36.134.91.96:17330/bytesailing_base?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: fjhx2012mysql
-                    password: 3PN-Mzn#vnP&q6d
-                iot:
-                    url: jdbc:mysql://36.134.91.96:17330/bytesailing_iot?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                    username: fjhx2012mysql
-                    password: 3PN-Mzn#vnP&q6d
+  datasource:
+    dynamic:
+      strict: true
+      primary: base
+      datasource:
+        base:
+          url: jdbc:mysql://36.134.91.96:12333/bytesailing_base?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=Asia/Shanghai
+          username: root
+          password: Fjhx@pwd123
 
     # redis 配置
-    redis:
-        # 地址
-        host: 36.134.91.96
-        # 端口,默认为6379
-        port: 6379
-        # 数据库索引
-        database: 5
-        # 密码
-        password: 123qwe!@#
-        # 连接超时时间
-        timeout: 10s
-        lettuce:
-            pool:
-                # 连接池中的最小空闲连接
-                min-idle: 0
-                # 连接池中的最大空闲连接
-                max-idle: 8
-                # 连接池的最大数据库连接数
-                max-active: 8
-                # #连接池最大阻塞等待时间(使用负值表示没有限制)
-                max-wait: -1ms
+  redis:
+    # 地址
+    host: 36.134.91.96
+    # 端口,默认为6379
+    port: 13444
+    # 数据库索引
+    database: 5
+    # 密码
+    password: Fjhx@pwd123
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms

+ 30 - 84
ruoyi-admin/src/main/resources/application-prod.yml

@@ -1,88 +1,34 @@
 # 数据源配置
 spring:
-    datasource:
-        type: com.alibaba.druid.pool.DruidDataSource
-        driverClassName: com.mysql.cj.jdbc.Driver
-        druid:
-            # 主库数据源
-            master:
-                url: jdbc:mysql://36.134.91.96:17330/ry_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: fjhx2012mysql
-                password: 3PN-Mzn#vnP&q6d
-            # 从库数据源
-            slave:
-                # 从数据源开关/默认关闭
-                enabled: false
-                url:
-                username:
-                password:
-            # 初始连接数
-            initialSize: 5
-            # 最小连接池数量
-            minIdle: 10
-            # 最大连接池数量
-            maxActive: 20
-            # 配置获取连接等待超时的时间
-            maxWait: 60000
-            # 配置连接超时时间
-            connectTimeout: 30000
-            # 配置网络超时时间
-            socketTimeout: 60000
-            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-            timeBetweenEvictionRunsMillis: 60000
-            # 配置一个连接在池中最小生存的时间,单位是毫秒
-            minEvictableIdleTimeMillis: 300000
-            # 配置一个连接在池中最大生存的时间,单位是毫秒
-            maxEvictableIdleTimeMillis: 900000
-            # 配置检测连接是否有效
-            validationQuery: SELECT 1 FROM DUAL
-            testWhileIdle: true
-            testOnBorrow: false
-            testOnReturn: false
-            webStatFilter:
-                enabled: true
-            statViewServlet:
-                enabled: true
-                # 设置白名单,不填则允许所有访问
-                allow:
-                url-pattern: /druid/*
-                # 控制台管理用户名和密码
-                login-username: ruoyi
-                login-password: 123456
-            filter:
-                stat:
-                    enabled: true
-                    # 慢SQL记录
-                    log-slow-sql: true
-                    slow-sql-millis: 1000
-                    merge-sql: true
-                wall:
-                    config:
-                        multi-statement-allow: true
+  datasource:
+    dynamic:
+      strict: true
+      primary: base
+      datasource:
+        base:
+          url: jdbc:mysql://36.134.91.96:12333/bytesailing_base?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=Asia/Shanghai
+          username: root
+          password: Fjhx@pwd123
 
     # redis 配置
-    redis:
-        # 地址
-        host: 36.134.91.96
-        # 端口,默认为6379
-        port: 6379
-        # 数据库索引
-        database: 5
-        # 密码
-        password: 123qwe!@#
-        # 连接超时时间
-        timeout: 10s
-        lettuce:
-            pool:
-                # 连接池中的最小空闲连接
-                min-idle: 0
-                # 连接池中的最大空闲连接
-                max-idle: 8
-                # 连接池的最大数据库连接数
-                max-active: 8
-                # #连接池最大阻塞等待时间(使用负值表示没有限制)
-                max-wait: -1ms
-
-server:
-    servlet:
-        context-path: /prod-api
+  redis:
+    # 地址
+    host: 36.134.91.96
+    # 端口,默认为6379
+    port: 13444
+    # 数据库索引
+    database: 5
+    # 密码
+    password: Fjhx@pwd123
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms

+ 30 - 84
ruoyi-admin/src/main/resources/application-test.yml

@@ -1,88 +1,34 @@
 # 数据源配置
 spring:
-    datasource:
-        type: com.alibaba.druid.pool.DruidDataSource
-        driverClassName: com.mysql.cj.jdbc.Driver
-        druid:
-            # 主库数据源
-            master:
-                url: jdbc:mysql://36.134.91.96:17330/ry_test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-                username: fjhx2012mysql
-                password: 3PN-Mzn#vnP&q6d
-            # 从库数据源
-            slave:
-                # 从数据源开关/默认关闭
-                enabled: false
-                url:
-                username:
-                password:
-            # 初始连接数
-            initialSize: 5
-            # 最小连接池数量
-            minIdle: 10
-            # 最大连接池数量
-            maxActive: 20
-            # 配置获取连接等待超时的时间
-            maxWait: 60000
-            # 配置连接超时时间
-            connectTimeout: 30000
-            # 配置网络超时时间
-            socketTimeout: 60000
-            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-            timeBetweenEvictionRunsMillis: 60000
-            # 配置一个连接在池中最小生存的时间,单位是毫秒
-            minEvictableIdleTimeMillis: 300000
-            # 配置一个连接在池中最大生存的时间,单位是毫秒
-            maxEvictableIdleTimeMillis: 900000
-            # 配置检测连接是否有效
-            validationQuery: SELECT 1 FROM DUAL
-            testWhileIdle: true
-            testOnBorrow: false
-            testOnReturn: false
-            webStatFilter:
-                enabled: true
-            statViewServlet:
-                enabled: true
-                # 设置白名单,不填则允许所有访问
-                allow:
-                url-pattern: /druid/*
-                # 控制台管理用户名和密码
-                login-username: ruoyi
-                login-password: 123456
-            filter:
-                stat:
-                    enabled: true
-                    # 慢SQL记录
-                    log-slow-sql: true
-                    slow-sql-millis: 1000
-                    merge-sql: true
-                wall:
-                    config:
-                        multi-statement-allow: true
+  datasource:
+    dynamic:
+      strict: true
+      primary: base
+      datasource:
+        base:
+          url: jdbc:mysql://36.134.91.96:12333/bytesailing_base?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=Asia/Shanghai
+          username: root
+          password: Fjhx@pwd123
 
     # redis 配置
-    redis:
-        # 地址
-        host: 36.134.91.96
-        # 端口,默认为6379
-        port: 6379
-        # 数据库索引
-        database: 5
-        # 密码
-        password: 123qwe!@#
-        # 连接超时时间
-        timeout: 10s
-        lettuce:
-            pool:
-                # 连接池中的最小空闲连接
-                min-idle: 0
-                # 连接池中的最大空闲连接
-                max-idle: 8
-                # 连接池的最大数据库连接数
-                max-active: 8
-                # #连接池最大阻塞等待时间(使用负值表示没有限制)
-                max-wait: -1ms
-
-server:
-    servlet:
-        context-path: /test-api
+  redis:
+    # 地址
+    host: 36.134.91.96
+    # 端口,默认为6379
+    port: 13444
+    # 数据库索引
+    database: 5
+    # 密码
+    password: Fjhx@pwd123
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms

+ 1 - 12
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java

@@ -14,17 +14,6 @@ import java.util.concurrent.*;
  **/
 @Configuration
 public class ThreadPoolConfig {
-    // 核心线程池大小
-    private int corePoolSize = 50;
-
-    // 最大可创建的线程数
-    private int maxPoolSize = 200;
-
-    // 队列最大长度
-    private int queueCapacity = 1000;
-
-    // 线程池维护线程所允许的空闲时间
-    private int keepAliveSeconds = 300;
 
     public static final String threadPoolTaskExecutor = "threadPoolTaskExecutor";
 
@@ -45,7 +34,7 @@ public class ThreadPoolConfig {
      */
     @Bean(name = "scheduledExecutorService")
     protected ScheduledExecutorService scheduledExecutorService() {
-        return new ScheduledThreadPoolExecutor(corePoolSize,
+        return new ScheduledThreadPoolExecutor(50,
                 new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
                 new ThreadPoolExecutor.CallerRunsPolicy()) {
             @Override

+ 86 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis/RemoveParam.java

@@ -0,0 +1,86 @@
+package com.ruoyi.framework.mybatis;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.ReflectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.context.annotation.Configuration;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Configuration
+public class RemoveParam implements BeanPostProcessor {
+
+    public static final Map<String, Boolean> updateUserMap = new ConcurrentHashMap<>();
+    public static final Map<String, Boolean> updateTimeMap = new ConcurrentHashMap<>();
+
+    @Override
+    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+
+        if (bean instanceof ServiceImpl) {
+            Class<?> beanClass = bean.getClass();
+            try {
+                // spring代理对象类名转换成普通对象类名
+                String name = beanClass.getName().split("\\$")[0];
+                Class<?> aClass = Class.forName(name);
+                Type genericSuperclass = aClass.getGenericSuperclass();
+                if (genericSuperclass instanceof ParameterizedType) {
+                    ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
+                    Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+                    Type actualTypeArgument = actualTypeArguments[1];
+
+                    Class<?> entityClass = Class.forName(actualTypeArgument.getTypeName());
+
+                    String tableName;
+                    TableName annotation = entityClass.getAnnotation(TableName.class);
+                    if (annotation != null && annotation.value() != null) {
+                        tableName = annotation.value();
+                    } else {
+                        tableName = StrUtil.toUnderlineCase(entityClass.getSimpleName());
+                    }
+
+                    Field[] fields = ReflectUtil.getFields(entityClass);
+
+                    // 字段
+                    for (Field field : fields) {
+                        TableField tableField = field.getAnnotation(TableField.class);
+                        if (tableField == null) {
+                            continue;
+                        }
+
+                        FieldFill fill = tableField.fill();
+                        if (ObjectUtil.notEqual(fill, FieldFill.INSERT_UPDATE)) {
+                            continue;
+                        }
+
+                        if (ObjectUtil.equals(tableField.value(), "update_time") || field.getName().equals("updateTime")) {
+                            RemoveParam.updateTimeMap.put(tableName, true);
+                            continue;
+                        }
+
+                        if (ObjectUtil.equals(tableField.value(), "update_user") || field.getName().equals("updateUser")) {
+                            RemoveParam.updateUserMap.put(tableName, true);
+                        }
+                    }
+
+                    RemoveParam.updateTimeMap.putIfAbsent(tableName, false);
+                    RemoveParam.updateUserMap.putIfAbsent(tableName, false);
+                }
+            } catch (ClassNotFoundException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        return bean;
+    }
+
+}

+ 47 - 18
ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis/interceptor/LogicInterceptor.java

@@ -1,5 +1,6 @@
 package com.ruoyi.framework.mybatis.interceptor;
 
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.druid.pool.DruidDataSource;
 import com.alibaba.druid.stat.JdbcDataSourceStat;
@@ -13,6 +14,9 @@ import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import com.baomidou.mybatisplus.extension.plugins.inner.BaseMultiTableInnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
 import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.config.ThreadPoolConfig;
+import com.ruoyi.framework.mybatis.RemoveParam;
 import com.ruoyi.framework.mybatis.holder.LogicHolder;
 import lombok.extern.slf4j.Slf4j;
 import net.sf.jsqlparser.JSQLParserException;
@@ -43,10 +47,8 @@ import org.springframework.stereotype.Component;
 
 import javax.sql.DataSource;
 import java.sql.Connection;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
 
 @Slf4j
 @Component
@@ -74,23 +76,29 @@ public class LogicInterceptor extends BaseMultiTableInnerInterceptor implements
      */
     private static final Map<String, List<String>> includeLogicIdTableNameMap = new HashMap<>();
 
-    public LogicInterceptor(DataSource dataSource) {
+    public LogicInterceptor(DataSource dataSource, ThreadPoolConfig threadPoolConfig) {
         DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource) dataSource;
         Map<String, DataSource> dataSources = dynamicRoutingDataSource.getDataSources();
+
+        List<CompletableFuture<Void>> list = new ArrayList<>();
         dataSources.forEach((k, v) -> {
-            // 获取dataSourceStat
-            JdbcDataSourceStat dataSourceStat = ((DruidDataSource) ((ItemDataSource) v).getRealDataSource()).getDataSourceStat();
-            // 获取链接url
-            String url = dataSourceStat.getUrl();
-            // 获取数据库名
-            String dbName = url.split("/")[3].split("\\?")[0];
-            // 查询包含逻辑删除字段的表名sql
-            String sql = "SELECT table_name FROM information_schema.COLUMNS WHERE table_schema = ? AND column_name = ?";
-            // 执行sql找出不包含逻辑删除字段的表名
-            List<String> notContainsDelFlagTableNameList = new JdbcTemplate(v).queryForList(sql, String.class, dbName, delFlagName);
-            // 数据赋值
-            includeLogicIdTableNameMap.put(dataSourceStat.getName(), notContainsDelFlagTableNameList);
+            CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
+                // 获取dataSourceStat
+                JdbcDataSourceStat dataSourceStat = ((DruidDataSource) ((ItemDataSource) v).getRealDataSource()).getDataSourceStat();
+                // 获取链接url
+                String url = dataSourceStat.getUrl();
+                // 获取数据库名
+                String dbName = url.split("/")[3].split("\\?")[0];
+                // 查询包含逻辑删除字段的表名sql
+                String sql = "SELECT table_name FROM information_schema.COLUMNS WHERE table_schema = ? AND column_name = ?";
+                // 执行sql找出不包含逻辑删除字段的表名
+                List<String> notContainsDelFlagTableNameList = new JdbcTemplate(v).queryForList(sql, String.class, dbName, delFlagName);
+                // 数据赋值
+                includeLogicIdTableNameMap.put(dataSourceStat.getName(), notContainsDelFlagTableNameList);
+            }, threadPoolConfig.threadPoolTaskExecutor());
+            list.add(completableFuture);
         });
+        list.forEach(CompletableFuture::join);
     }
 
     @Override
@@ -123,12 +131,21 @@ public class LogicInterceptor extends BaseMultiTableInnerInterceptor implements
                     return;
                 }
 
-                sql = "UPDATE " + table.getName() + " SET " + delFlagName + " = " + delValue;
+                String tableName = table.getName();
+
+                Boolean updateUser = RemoveParam.updateUserMap.get(tableName);
+                Boolean updateTime = RemoveParam.updateTimeMap.get(tableName);
+
+                sql = "UPDATE " + tableName + " SET " +
+                        delFlagName + " = " + delValue +
+                        (Boolean.TRUE.equals(updateUser) ? ", update_user = " + getUserUniqueId() : StringPool.EMPTY) +
+                        (Boolean.TRUE.equals(updateTime) ? ", update_time = '" + DateUtil.now() + "'" : StringPool.EMPTY);
 
                 Expression where = delete.getWhere();
                 if (where != null) {
                     sql += " WHERE " + where;
                 }
+
                 mpBs.sql(sql);
             } catch (JSQLParserException e) {
                 throw new RuntimeException(e);
@@ -310,4 +327,16 @@ public class LogicInterceptor extends BaseMultiTableInnerInterceptor implements
         return !tableNameList.contains(name);
     }
 
+
+    /**
+     * 获取用户id
+     */
+    private Long getUserUniqueId() {
+        try {
+            return SecurityUtils.getUserId();
+        } catch (Exception e) {
+            return -1L;
+        }
+    }
+
 }