Kaynağa Gözat

feature 解决异步任务无法切库的问题

xiahan 3 ay önce
ebeveyn
işleme
200391c0c9

+ 5 - 0
zhsw-common/pom.xml

@@ -70,6 +70,11 @@
             <artifactId>aspose-words</artifactId>
             <version>21.1.0</version>
         </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>transmittable-thread-local</artifactId>
+            <version>2.14.4</version>
+        </dependency>
         <!--        <dependency>-->
 <!--            <groupId>org.docx4j</groupId>-->
 <!--            <artifactId>docx4j</artifactId>-->

+ 0 - 32
zhsw-common/src/main/java/com/rongwei/zhsw/system/config/AsyncConfig.java

@@ -1,32 +0,0 @@
-package com.rongwei.zhsw.system.config;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
-import org.springframework.scheduling.annotation.AsyncConfigurer;
-
-import java.lang.reflect.Method;
-
-/**
- * AsyncConfig class
- *
- * @author XH
- * @date 2025/04/03
- */
-public class AsyncConfig implements AsyncConfigurer {
-    private static final Logger log = LoggerFactory.getLogger(AsyncConfig.class);
-
-    @Override
-    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
-        return new CustomAsyncExceptionHandler();
-    }
-
-    private static class CustomAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
-        @Override
-        public void handleUncaughtException(Throwable ex, Method method, Object... params) {
-            // 记录异常日志或发送告警
-            log.error("Async method error: {}", ex.getMessage());
-            ex.printStackTrace();
-        }
-    }
-}

+ 34 - 0
zhsw-common/src/main/java/com/rongwei/zhsw/system/config/ContextHolder.java

@@ -0,0 +1,34 @@
+package com.rongwei.zhsw.system.config;
+
+import com.alibaba.ttl.TransmittableThreadLocal;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * ContextHolder class
+ *
+ * @author XH
+ * @date 2025/04/10
+ */
+public class ContextHolder {
+    private static final TransmittableThreadLocal<Map<String, String>> context = new TransmittableThreadLocal<>();
+
+    public static void setValue(String key, String value) {
+        Map<String, String> map = context.get();
+        if (map == null) {
+            map = new HashMap<>();
+            context.set(map);
+        }
+        map.put(key, value);
+    }
+
+    public static String getValue(String key) {
+        Map<String, String> map = context.get();
+        return map != null ? map.get(key) : null;
+    }
+
+    public static void clear() {
+        context.remove();
+    }
+}

+ 2 - 3
zhsw-common/src/main/java/com/rongwei/zhsw/system/config/MybatisConfig.java

@@ -7,7 +7,6 @@ import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
 import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
-import com.rongwei.rwcommonconfig.config.interceptor.QuerySqlAdaptationInterceptor;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.LongValue;
 import org.apache.ibatis.mapping.MappedStatement;
@@ -34,8 +33,8 @@ public class MybatisConfig {
      * @return
      */
     @Bean
-    public QuerySqlAdaptationInterceptor querySqlAdaptationInterceptor(){
-        QuerySqlAdaptationInterceptor sqlAdaptation = new QuerySqlAdaptationInterceptor();
+    public ZHSWQuerySqlAdaptationInterceptor querySqlAdaptationInterceptor(){
+        ZHSWQuerySqlAdaptationInterceptor sqlAdaptation = new ZHSWQuerySqlAdaptationInterceptor();
         return sqlAdaptation;
     }
 

+ 0 - 58
zhsw-common/src/main/java/com/rongwei/zhsw/system/config/ThreadPoolConfig.java

@@ -1,58 +0,0 @@
-package com.rongwei.zhsw.system.config;
-
-import cn.hutool.core.thread.ExecutorBuilder;
-import cn.hutool.core.thread.ThreadFactoryBuilder;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.task.TaskDecorator;
-import org.springframework.scheduling.annotation.AsyncConfigurer;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
-import org.springframework.web.context.request.RequestAttributes;
-import org.springframework.web.context.request.RequestContextHolder;
-
-import javax.annotation.PreDestroy;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-/**
- * ThreadPoolConfig class
- *
- * @author XH
- * @date 2023/12/18
- */
-
-@Configuration
-public class ThreadPoolConfig implements AsyncConfigurer {
-
-    @Bean("zhswThreadPool")
-    @Override
-    public ThreadPoolTaskExecutor getAsyncExecutor() {
-        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
-        executor.setCorePoolSize(4);
-        executor.setMaxPoolSize(8);
-        executor.setQueueCapacity(16);
-        executor.setThreadNamePrefix("zhsw-");
-        executor.setTaskDecorator(new RequestContextTaskDecorator());
-        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
-        executor.initialize();
-        return executor;
-    }
-
-    static class RequestContextTaskDecorator implements TaskDecorator {
-        @Override
-        public Runnable decorate(Runnable runnable) {
-            // 获取主线程的请求上下文
-            RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
-            return () -> {
-                try {
-                    // 将主线程的请求上下文绑定到子线程
-                    RequestContextHolder.setRequestAttributes(requestAttributes, true); // true 表示继承模式
-                    runnable.run();
-                } finally {
-                    // 清理子线程的上下文,避免内存泄漏
-                    RequestContextHolder.resetRequestAttributes(); // 始终清理上下文
-                }
-            };
-        }
-    }
-}

+ 45 - 0
zhsw-common/src/main/java/com/rongwei/zhsw/system/config/TtlThreadPoolConfig.java

@@ -0,0 +1,45 @@
+package com.rongwei.zhsw.system.config;
+
+import com.alibaba.ttl.TtlRunnable;
+import com.alibaba.ttl.threadpool.TtlExecutors;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.task.TaskDecorator;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+/**
+ * TtlThreadPoolConfig class
+ *
+ * @author XH
+ * @date 2025/04/10
+ */
+@Configuration
+@EnableAsync
+public class TtlThreadPoolConfig {
+    @Bean(name = "zhswThreadPool")
+    public Executor ttlTaskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(4);
+        executor.setMaxPoolSize(8);
+        executor.setQueueCapacity(16);
+        executor.setThreadNamePrefix("zhsw-");
+        executor.setTaskDecorator(new TtlTaskDecorator());
+        // executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        executor.initialize();
+        return executor;
+    }
+
+    /**
+     * 自定义 TaskDecorator,用 TTL 包装 Runnable
+     */
+    static class TtlTaskDecorator implements TaskDecorator {
+        @Override
+        public Runnable decorate(Runnable runnable) {
+            // 将原始 Runnable 包装为 TtlRunnable
+            return TtlRunnable.get(runnable,false);
+        }
+    }
+}

+ 202 - 0
zhsw-common/src/main/java/com/rongwei/zhsw/system/config/ZHSWQuerySqlAdaptationInterceptor.java

@@ -0,0 +1,202 @@
+package com.rongwei.zhsw.system.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.rongwei.commonservice.service.RedisService;
+import com.rongwei.rwadmincommon.system.vo.SysUserVo;
+import com.rongwei.rwcommon.utils.Constants;
+import com.rongwei.rwcommon.utils.SqlAdaptationUtil;
+import com.rongwei.rwcommon.utils.StringUtils;
+import org.apache.ibatis.binding.MapperMethod;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.plugin.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Field;
+import java.sql.Connection;
+import java.util.Properties;
+
+/**
+ * 自定义查询拦截器方法、适配多数据库语法
+ */
+@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
+public class ZHSWQuerySqlAdaptationInterceptor implements Interceptor {
+
+    private static final Logger logger = LoggerFactory.getLogger(ZHSWQuerySqlAdaptationInterceptor.class);
+
+    @Value("${saas.tenantmode:NONE}")
+    private String saasmode;
+
+    @Autowired
+    private RedisService redisService;
+
+    @Autowired
+    private DruidDataSource datasource;
+
+    @Override
+    public Object intercept(Invocation invocation) throws Throwable {
+//        DruidDataSource datasource = (DruidDataSource)DynamicDataSource.dataSourcesMap.get(DynamicDataSource.getDataSource());
+        // 获取数据库类型
+        String dbType = datasource.getDbType();
+        // 方法一
+        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
+        //映射工具
+//        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
+//        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
+        //先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,其实现类是BaseStatementHandler,然后就到BaseStatementHandler的成员变量mappedStatement
+//        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
+        //id为执行的mapper方法的全路径名,如com.uv.dao.UserMapper.insertUser
+        BoundSql boundSql = statementHandler.getBoundSql();
+
+        //获取到原始sql语句
+        String sql = boundSql.getSql();
+        SqlAdaptationUtil sqlAdaptation = new SqlAdaptationUtil();
+        String mSql = sqlAdaptation.modifySql(sqlAdaptation.commonRuleAnalysis(sql),dbType);
+        //通过反射修改sql语句
+        Field field = boundSql.getClass().getDeclaredField("sql");
+        field.setAccessible(true);
+        // dao参数
+        Object parObj = statementHandler.getParameterHandler().getParameterObject();
+        // SaaS环境下schema切换
+        if("DATASOURCE".equals(saasmode)){
+            logger.info("saas切换");
+            String schema = null;
+            try{
+                schema = this.getSchema();
+            }catch (Exception e){
+                logger.info("通过上下文对象获取schema失败");
+            }
+            // 判断是否有参数(appointSchema)指定schema
+            if(parObj instanceof MapperMethod.ParamMap){
+                MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap)parObj;
+                if(paramMap.containsKey("appointSchema") && paramMap.get("appointSchema") != null){
+                    String appointSchema = paramMap.get("appointSchema").toString();
+                    schema = appointSchema;
+                }
+            }
+            logger.info("schema:"+schema);
+            if(StringUtils.isNotBlank(schema)){
+                // 多租户schema切换方案一:通过 USE databaseName; 实现切换
+                mSql = "USE " + schema + ";" + mSql;
+                logger.info("mSql:"+mSql);
+                // 多租户schema切换方案二:直接获取Connection设置schema
+                /*Object[] objs = invocation.getArgs();
+                Connection conn = (Connection)objs[0];
+                conn.setSchema(schema);*/
+            }else{
+//                throw new Exception("SaaS模式下查不到相应schema");
+                logger.warn("SaaS模式下查不到相应schema");
+            }
+            /*Connection o = (Connection)invocation.getArgs()[0];
+            o.setSchema(schema);
+            */
+        }
+
+        field.set(boundSql, mSql);
+        //sql语句类型 select、delete、insert、update
+        /*if(SqlCommandType.SELECT == mappedStatement.getSqlCommandType()){
+        }*/
+
+        // 返回
+        return invocation.proceed();
+    }
+
+    @Override
+    public Object plugin(Object target) {
+        return Plugin.wrap(target, this);
+    }
+
+    @Override
+    public void setProperties(Properties properties) {
+    }
+
+    /**
+     * SaaS模式下获取当前租户的数据库名
+     * @return
+     * @throws Exception
+     */
+    private String getSchema() throws Exception{
+        Long startTime = System.currentTimeMillis();
+        String schema = null;
+        schema = ContextHolder.getValue("dsKey");
+        if(StringUtils.isNotBlank(schema)){
+            return schema;
+        }
+
+        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        if(attributes == null){
+            logger.error("ServletRequestAttributes为null");
+            throw new Exception("ServletRequestAttributes为null");
+        }
+        HttpServletRequest request = attributes.getRequest();
+        if(request == null){
+            logger.error("HttpServletRequest为null");
+            throw new Exception("HttpServletRequest为null");
+        }
+
+        schema = request.getHeader("schema");
+        if(StringUtils.isNotBlank(schema)) {
+            return schema;
+        }
+
+        String token = request.getHeader("token");
+        logger.info("token:"+token);
+//        if(StringUtils.isBlank(token)){
+//            String incontrolToken = request.getHeader("incontrol-token");
+//            Object tokenDskey = request.getAttribute(Constants.SAAS_LOGIN_TOKEN);
+//            // 登录功能特殊处理获取DsKey
+//            if(tokenDskey != null){
+//                logger.info("tokenDskey:"+tokenDskey);
+//                schema = (String) tokenDskey;
+//            }
+//            // 某些特殊功能incontrolToken也可以作为token
+//            else if(StringUtils.isNotBlank(incontrolToken)){
+//                logger.info("incontrolToken:"+incontrolToken);
+//                schema = getSchemaByToken(incontrolToken);
+//            }
+//            // 某些特殊功能token放入线程全局变量中
+//            else if(StringUtils.isNotBlank(ThreadLocalResource.token.get())){
+//                logger.info("ThreadToken:"+ThreadLocalResource.token.get());
+//                token = ThreadLocalResource.token.get();
+//                schema = getSchemaByToken(token);
+//            }
+//        } else{
+//            schema = getSchemaByToken(token);
+//            System.out.println("Dskey:"+schema);
+//        }
+        Object tokenDskey = request.getAttribute(Constants.SAAS_LOGIN_TOKEN);
+        if(tokenDskey != null && StringUtils.isNotBlank(tokenDskey.toString())){
+            schema = (String) tokenDskey;
+        }else {
+            schema = getSchemaByToken(token);
+        }
+        System.out.println("Dskey:"+schema);
+        Long endTime = System.currentTimeMillis();
+        System.out.println("查找schema时间为:"+(endTime-startTime));
+        return schema;
+    }
+
+    /**
+     * 根据token获取多租户模式的schema
+     * @param token
+     * @return
+     */
+    private String getSchemaByToken(String token){
+        SysUserVo currUser = null;
+        if(StringUtils.isNotEmpty(token)){
+            currUser = redisService.getLoginUser(token);
+        }
+        String schema = null;
+        if(currUser != null){
+            schema = currUser.getTenantDo().getDskey();
+        }
+        return schema;
+    }
+
+}

+ 1 - 1
zhsw-common/src/main/java/com/rongwei/zhsw/system/importListener/MeterReadingRecordListener.java

@@ -117,7 +117,7 @@ public class MeterReadingRecordListener extends AnalysisEventListener<ImportMete
 
         List<SwUserManagementDo> allAccountData = new ArrayList<>();
         // 获取户号信息
-        Lists.partition(accountNumList, 5000).parallelStream().forEach(accountNum -> {
+        Lists.partition(accountNumList, 5000).forEach(accountNum -> {
             allAccountData.addAll(swUserManagementService.list(new LambdaQueryWrapper<SwUserManagementDo>()
                     .eq(BaseDo::getDeleted, "0")
                     .in(SwUserManagementDo::getUsernumber, accountNumList)));

+ 1 - 1
zhsw-common/src/main/java/com/rongwei/zhsw/system/service/ImportExcelService.java

@@ -12,5 +12,5 @@ import javax.servlet.http.HttpServletRequest;
  */
 public interface ImportExcelService {
 
-    R meterReadingRecord(String fileId, HttpServletRequest httpServletRequest);
+    R meterReadingRecord(String fileId);
 }

+ 18 - 23
zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/BillGenerationServiceImpl.java

@@ -7,8 +7,8 @@ import com.rongwe.zhsw.system.domain.SwWaterUsageEntryDo;
 import com.rongwei.commonservice.service.RedisService;
 import com.rongwei.rwadmincommon.system.vo.SysUserVo;
 import com.rongwei.rwcommon.base.BaseDo;
-import com.rongwei.rwcommon.utils.Constants;
 import com.rongwei.rwcommon.utils.SecurityUtil;
+import com.rongwei.zhsw.system.config.ContextHolder;
 import com.rongwei.zhsw.system.utils.ZHSWCommonUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -20,9 +20,7 @@ import org.springframework.transaction.TransactionDefinition;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.support.DefaultTransactionDefinition;
 import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
 
-import javax.servlet.http.HttpServletRequest;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
@@ -69,21 +67,17 @@ public class BillGenerationServiceImpl {
      * @param attributes
      */
     @Async(value = "zhswThreadPool")
-    public void asyncGenerateBill(List<SwWaterUsageEntryDo> swWaterUsageEntryDoList, HttpServletRequest httpServletRequest, String dskey) {
+    public void asyncGenerateBill(List<SwWaterUsageEntryDo> swWaterUsageEntryDoList) {
         if (swWaterUsageEntryDoList == null || swWaterUsageEntryDoList.isEmpty()) {
             log.error("暂无需要生成账单的信息");
             return;
         }
-        if(httpServletRequest==null){
-            httpServletRequest =((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
-        }
-        log.info("httpServletRequest是否为空:{},所属库名:{}", httpServletRequest == null, dskey);
-        httpServletRequest.setAttribute(Constants.SAAS_LOGIN_TOKEN, dskey);
         generateBill(swWaterUsageEntryDoList);
     }
 
-
     public void generateBill(List<SwWaterUsageEntryDo> swWaterUsageEntryDoList) {
+        String dsKey = ContextHolder.getValue("dsKey");
+        log.info("上下文信息为:{},dsKey:{}", RequestContextHolder.getRequestAttributes(), dsKey);
         log.debug("需要生成账单的抄表记录为:{}", swWaterUsageEntryDoList);
         // 对数据按照抄表日期排序
         List<SwWaterUsageEntryDo> collect = swWaterUsageEntryDoList.stream()
@@ -173,7 +167,6 @@ public class BillGenerationServiceImpl {
             userSaveList.add(swUserManagementDo);
             saveUsageEntryList.add(usageEntryDo);
         }
-        ;
         dataSave(saveList, saveUsageEntryList, userSaveList);
     }
 
@@ -181,33 +174,33 @@ public class BillGenerationServiceImpl {
     public void generateBill(String id) {
         log.info("开始给抄表记录:{},生成账单信息", id);
         SwWaterUsageEntryDo swWaterUsageEntryDo = swWaterUsageEntryService.getById(id);
+        SysUserVo currentUser = ZHSWCommonUtils.getCurrentUser();
+        ContextHolder.setValue("dskey", currentUser.getTenantDo().getDskey());
         this.generateBill(Collections.singletonList(swWaterUsageEntryDo));
     }
 
 
-    public void generateBill(List<String> ids, boolean a, HttpServletRequest httpServletRequest) {
+    public void generateBill(List<String> ids, boolean a) {
         if (ids.isEmpty()) {
             log.error("抄表记录ID为空");
             return;
         }
-        String token = httpServletRequest.getHeader("token");
-        log.info("token:{}", token);
-        SysUserVo loginUser = redisService.getLoginUser(token);
-        log.info("获取到的用户信息为:{}", loginUser);
-        String dskey = loginUser.getTenantDo().getDskey();
-        log.info("开始给抄表记录:{},生成账单信息", ids);
-        this.asyncGenerateBill(swWaterUsageEntryService.getBaseMapper().selectBatchIds(ids), httpServletRequest, dskey);
+        SysUserVo currentUser = ZHSWCommonUtils.getCurrentUser();
+        ContextHolder.setValue("dsKey", currentUser.getTenantDo().getDskey());
+        this.asyncGenerateBill(swWaterUsageEntryService.getBaseMapper().selectBatchIds(ids));
+        ContextHolder.clear();
     }
 
 
-    public void generateBill(HttpServletRequest request) {
+    public void generateBill() {
         List<SwWaterUsageEntryDo> list = swWaterUsageEntryService.list(new LambdaQueryWrapper<SwWaterUsageEntryDo>()
                 .eq(SwWaterUsageEntryDo::getDeleted, "0")
                 .eq(SwWaterUsageEntryDo::getState, 0));
         log.info("开始给抄表记录:{},生成账单信息", list.stream().map(SwWaterUsageEntryDo::getId).collect(Collectors.toList()));
         SysUserVo currentUser = ZHSWCommonUtils.getCurrentUser();
-        String dskey = currentUser.getTenantDo().getDskey();
-        this.asyncGenerateBill(list, request, dskey);
+        ContextHolder.setValue("dskey", currentUser.getTenantDo().getDskey());
+        this.asyncGenerateBill(list);
+        ContextHolder.clear();
     }
 
     /**
@@ -243,6 +236,8 @@ public class BillGenerationServiceImpl {
             e.printStackTrace();
             transactionManager.rollback(status);
             log.error("账单保存异常");
+        }finally {
+            ContextHolder.clear();
         }
 
     }
@@ -255,7 +250,7 @@ public class BillGenerationServiceImpl {
      */
     public SwBillManagementUnpaidDo produceBill(SwUserManagementDo swUserManagementDo, SwWaterUsageEntryDo swWaterUsageEntryDo) {
         // 上次抄表数
-        BigDecimal lastreading = swWaterUsageEntryDo.getLastreading()==null?BigDecimal.ZERO:swWaterUsageEntryDo.getLastreading();
+        BigDecimal lastreading = swWaterUsageEntryDo.getLastreading() == null ? BigDecimal.ZERO : swWaterUsageEntryDo.getLastreading();
         // 本次抄表数
         BigDecimal thisreading = swWaterUsageEntryDo.getThisreading();
 

+ 8 - 3
zhsw-common/src/main/java/com/rongwei/zhsw/system/service/impl/ImportExcelServiceImpl.java

@@ -7,6 +7,7 @@ import com.rongwei.rwadmincommon.system.vo.SysUserVo;
 import com.rongwei.rwcommon.base.R;
 import com.rongwei.rwcommoncomponent.file.dao.SysFileItemDao;
 import com.rongwei.rwcommonentity.commonservers.domain.SysFileItemDo;
+import com.rongwei.zhsw.system.config.ContextHolder;
 import com.rongwei.zhsw.system.importListener.MeterReadingRecordListener;
 import com.rongwei.zhsw.system.service.ImportExcelService;
 import com.rongwei.zhsw.system.utils.ZHSWCommonUtils;
@@ -17,6 +18,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
 
 import javax.servlet.http.HttpServletRequest;
 import java.io.File;
@@ -49,7 +52,8 @@ public class ImportExcelServiceImpl implements ImportExcelService {
      * @return
      */
     @Override
-    public R meterReadingRecord(String fileId, HttpServletRequest httpServletRequest) {
+    public R meterReadingRecord(String fileId) {
+        log.info("开始导入抄表记录");
         File file = readFile(fileId);
         // 数据读取
         long startTime = System.currentTimeMillis();
@@ -65,10 +69,11 @@ public class ImportExcelServiceImpl implements ImportExcelService {
         log.error("数据保存时长:{}", startTime - entTime);
         startTime = System.currentTimeMillis();
         SysUserVo currentUser = ZHSWCommonUtils.getCurrentUser();
-        String dskey = currentUser.getTenantDo().getDskey();
-        billGenerationService.asyncGenerateBill(saveList, httpServletRequest, dskey);
+        ContextHolder.setValue("dsKey",currentUser.getTenantDo().getDskey());
+        billGenerationService.asyncGenerateBill(saveList);
         entTime = System.currentTimeMillis();
         log.error("账单生成时长:{}", startTime - entTime);
+        ContextHolder.clear();
         return R.ok();
     }
 

+ 3 - 3
zhsw-server/src/main/java/com/rongwei/zhsw/system/controller/BillGenerationController.java

@@ -32,13 +32,13 @@ public class BillGenerationController {
     private BillGenerationServiceImpl billGenerationService;
 
     @PostMapping("/generate/{id}")
-    private R generateBill(@PathVariable("id") String id, HttpServletRequest request) {
+    private R generateBill(@PathVariable("id") String id) {
         billGenerationService.generateBill(id);
         return R.ok();
     }
     @PostMapping("/generate")
-    private R generateBill(HttpServletRequest request) {
-        billGenerationService.generateBill(request);
+    private R generateBill() {
+        billGenerationService.generateBill();
         return R.ok();
     }
 }

+ 2 - 2
zhsw-server/src/main/java/com/rongwei/zhsw/system/controller/ImportExcelController.java

@@ -27,7 +27,7 @@ public class ImportExcelController {
 
 
     @PostMapping("/meter-reading/{fileId}")
-    private R meterReadingRecord(@PathVariable("fileId") String fileId, HttpServletRequest httpServletRequest) {
-        return importExcelService.meterReadingRecord(fileId,httpServletRequest);
+    private R meterReadingRecord(@PathVariable("fileId") String fileId) {
+        return importExcelService.meterReadingRecord(fileId);
     }
 }

+ 25 - 16
zhsw-server/src/main/resources/logback-spring.xml

@@ -1,29 +1,38 @@
-<?xml version="1.0" encoding="UTF-8"?>
 <configuration scan="true" scanPeriod="60 seconds" debug="false">
     <contextName>logback</contextName>
-    <!--输出到控制台-->
+
+    <!-- 控制台输出 -->
     <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
         <encoder>
-
-            <pattern>%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
         </encoder>
     </appender>
 
-    <!--按天生成日志-->
+    <!-- 滚动文件输出 -->
     <appender name="logFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
-        <Prudent>true</Prudent>
         <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
-            <fileNamePattern>zhsw/%d{yyyy-MM-dd}/zhsw.%i.log</fileNamePattern>
-            <maxFileSize>5mb</maxFileSize>
-            <maxHistory>3</maxHistory>
-            <totalSizeCap>300MB</totalSizeCap>
+            <FileNamePattern>zhsw/%d{yyyy-MM-dd}/zhsw-app.%i.log</FileNamePattern>
+            <maxFileSize>4MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>1GB</totalSizeCap>
         </rollingPolicy>
-        <encoder>
-            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
-        </encoder>
+        <append>true</append>
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <Pattern>
+                %d{yyyy-MM-dd HH:mm:ss.SSS} [%X] [%thread] %-5level -%msg%n
+            </Pattern>
+        </layout>
     </appender>
-    <root level="error">
+
+    <!-- 指定包路径日志配置 -->
+    <logger name="com.rongwei" level="INFO" additivity="false">
+        <appender-ref ref="console"/>
+        <appender-ref ref="logFile" />
+    </logger>
+
+    <!-- Root Logger -->
+    <root level="ERROR">
         <appender-ref ref="console"/>
-        <appender-ref ref="logFile"/>
+        <appender-ref ref="logFile" />
     </root>
-</configuration>
+</configuration>