diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/log/FileUploadLogAppender.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/log/FileUploadLogAppender.java deleted file mode 100644 index 3958706..0000000 --- a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/log/FileUploadLogAppender.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.ruoyi.ccdi.project.log; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.PatternLayout; -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.FileAppender; -import ch.qos.logback.core.UnsynchronizedAppenderBase; -import lombok.extern.slf4j.Slf4j; -import org.slf4j.ILoggerFactory; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.text.SimpleDateFormat; -import java.util.Date; - -/** - * File upload batch log appender. - */ -@Slf4j -public class FileUploadLogAppender extends UnsynchronizedAppenderBase { - - private static final ThreadLocal> currentAppender = new ThreadLocal<>(); - - private PatternLayout layout; - - @Override - public void start() { - LoggerContext loggerContext = resolveLoggerContext(); - setContext(loggerContext); - - this.layout = new PatternLayout(); - this.layout.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"); - this.layout.setContext(loggerContext); - this.layout.start(); - - super.start(); - log.info("【文件上传日志】FileUploadLogAppender已启动"); - } - - @Override - protected void append(ILoggingEvent event) { - FileAppender appender = currentAppender.get(); - if (appender != null) { - appender.doAppend(event); - } - } - - /** - * Create a dedicated batch log file. - * - * @param uploadPath upload root path from ruoyi.profile - * @param projectId project id - * @param batchId batch id - */ - public static void createBatchLogFile(String uploadPath, Long projectId, String batchId) { - try { - LoggerContext loggerContext = resolveLoggerContext(); - - String timestamp = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date()); - String logDirPath = uploadPath + File.separator + "logs" + File.separator - + "file-upload" + File.separator + projectId; - - File logDir = new File(logDirPath); - if (!logDir.exists() && !logDir.mkdirs()) { - throw new IllegalStateException("无法创建批次日志目录: " + logDirPath); - } - - String logFilePath = logDirPath + File.separator + timestamp + ".log"; - - FileAppender appender = new FileAppender<>(); - appender.setContext(loggerContext); - appender.setFile(logFilePath); - - PatternLayout layout = new PatternLayout(); - layout.setPattern("%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"); - layout.setContext(loggerContext); - layout.start(); - - appender.setLayout(layout); - appender.setAppend(true); - appender.start(); - - currentAppender.set(appender); - - log.info("【文件上传日志】创建批次日志文件成功: path={}, batchId={}", logFilePath, batchId); - } catch (Exception e) { - log.error("【文件上传日志】创建批次日志文件失败: projectId={}, batchId={}", projectId, batchId, e); - } - } - - /** - * Close the current batch log file. - */ - public static void closeBatchLogFile() { - FileAppender appender = currentAppender.get(); - if (appender != null) { - appender.stop(); - currentAppender.remove(); - log.info("【文件上传日志】关闭批次日志文件"); - } - } - - private static LoggerContext resolveLoggerContext() { - ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory(); - if (loggerFactory instanceof LoggerContext loggerContext) { - return loggerContext; - } - throw new IllegalStateException("SLF4J logger factory is not a Logback LoggerContext"); - } -} diff --git a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java index 41352fb..c88919e 100644 --- a/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java +++ b/ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImpl.java @@ -7,7 +7,6 @@ import com.ruoyi.ccdi.project.domain.dto.CcdiFileUploadQueryDTO; import com.ruoyi.ccdi.project.domain.entity.CcdiBankStatement; import com.ruoyi.ccdi.project.domain.entity.CcdiFileUploadRecord; import com.ruoyi.ccdi.project.domain.vo.CcdiFileUploadStatisticsVO; -import com.ruoyi.ccdi.project.log.FileUploadLogAppender; import com.ruoyi.ccdi.project.mapper.CcdiBankStatementMapper; import com.ruoyi.ccdi.project.mapper.CcdiFileUploadRecordMapper; import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper; @@ -269,12 +268,8 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService { String batchId) { log.info("【文件上传】调度线程启动: projectId={}, batchId={}", projectId, batchId); - // 创建批次日志文件 - FileUploadLogAppender.createBatchLogFile(uploadPath, projectId, batchId); - - try { - // 循环提交任务 - for (int i = 0; i < tempFilePaths.size(); i++) { + // 循环提交任务 + for (int i = 0; i < tempFilePaths.size(); i++) { // Critical Fix #6: 检查线程中断状态 if (Thread.currentThread().isInterrupted()) { log.warn("【文件上传】调度线程被中断,停止提交剩余任务"); @@ -318,11 +313,7 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService { } } - log.info("【文件上传】调度线程完成: projectId={}, batchId={}", projectId, batchId); - } finally { - // 关闭批次日志文件 - FileUploadLogAppender.closeBatchLogFile(); - } + log.info("【文件上传】调度线程完成: projectId={}, batchId={}", projectId, batchId); } /** diff --git a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/log/FileUploadLogAppenderTest.java b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/log/FileUploadLogAppenderTest.java deleted file mode 100644 index d020ff5..0000000 --- a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/log/FileUploadLogAppenderTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.ruoyi.ccdi.project.log; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.FileAppender; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import java.lang.reflect.Field; -import java.nio.file.Path; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class FileUploadLogAppenderTest { - - @TempDir - Path tempDir; - - @AfterEach - void tearDown() { - FileUploadLogAppender.closeBatchLogFile(); - } - - @Test - void createBatchLogFile_shouldInitializeAppenderWithLoggerContext() throws Exception { - FileUploadLogAppender.createBatchLogFile(tempDir.toString(), 32L, "batch-1"); - - FileAppender appender = currentAppender(); - - assertNotNull(appender); - assertNotNull(appender.getContext()); - assertTrue(appender.isStarted()); - } - - @SuppressWarnings("unchecked") - private FileAppender currentAppender() throws Exception { - Field field = FileUploadLogAppender.class.getDeclaredField("currentAppender"); - field.setAccessible(true); - ThreadLocal> threadLocal = - (ThreadLocal>) field.get(null); - return threadLocal.get(); - } -} diff --git a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImplTest.java b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImplTest.java index 335fdbb..b7fe852 100644 --- a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImplTest.java +++ b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/service/impl/CcdiFileUploadServiceImplTest.java @@ -18,10 +18,13 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -56,9 +59,25 @@ class CcdiFileUploadServiceImplTest { @Mock private CcdiBankStatementMapper bankStatementMapper; + @Mock + private Executor fileUploadExecutor; + @TempDir Path tempDir; + @Test + void submitTasksAsync_shouldNotCreateLocalBatchLogFiles() throws Exception { + setField("uploadPath", tempDir.toString()); + + Path tempFile = createTempFile(); + CcdiFileUploadRecord record = buildRecord(); + + invokeSubmitTasksAsync(List.of(tempFile.toString()), List.of(record), "batch-1"); + + Path batchLogDir = tempDir.resolve("logs").resolve("file-upload").resolve(String.valueOf(PROJECT_ID)); + assertFalse(Files.exists(batchLogDir)); + } + @Test void processFileAsync_shouldKeepParsingUntilBankStatementsSaved() throws IOException { List events = new ArrayList<>(); @@ -279,6 +298,21 @@ class CcdiFileUploadServiceImplTest { return response; } + private void invokeSubmitTasksAsync(List tempFilePaths, + List records, + String batchId) throws Exception { + Method method = CcdiFileUploadServiceImpl.class.getDeclaredMethod("submitTasksAsync", + Long.class, Integer.class, List.class, List.class, String.class); + method.setAccessible(true); + method.invoke(service, PROJECT_ID, LSFX_PROJECT_ID, tempFilePaths, records, batchId); + } + + private void setField(String fieldName, Object value) throws Exception { + Field field = CcdiFileUploadServiceImpl.class.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(service, value); + } + private int findEventIndex(List events, String suffix) { for (int i = 0; i < events.size(); i++) { if (events.get(i).endsWith(suffix)) {