woody 11 сар өмнө
parent
commit
5a1ec83a48

+ 45 - 16
framework-export/src/main/java/com/chelvc/framework/export/support/DefaultExportHandler.java → framework-export/src/main/java/com/chelvc/framework/export/DefaultExportHandler.java

@@ -1,4 +1,4 @@
-package com.chelvc.framework.export.support;
+package com.chelvc.framework.export;
 
 import java.io.File;
 import java.io.FileOutputStream;
@@ -12,6 +12,7 @@ import java.util.Objects;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.stream.Collectors;
+import javax.annotation.PostConstruct;
 import javax.servlet.http.HttpServletResponse;
 
 import com.chelvc.framework.base.context.ApplicationContextHolder;
@@ -21,16 +22,20 @@ import com.chelvc.framework.common.util.AssertUtils;
 import com.chelvc.framework.common.util.ExcelUtils;
 import com.chelvc.framework.common.util.FileUtils;
 import com.chelvc.framework.common.util.ObjectUtils;
+import com.chelvc.framework.common.util.StringUtils;
 import com.chelvc.framework.common.util.ThreadUtils;
-import com.chelvc.framework.export.ExportHandler;
 import com.chelvc.framework.export.config.ExportProperties;
 import com.chelvc.framework.redis.context.RedisContextHolder;
 import com.google.common.collect.Lists;
 import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.poi.ss.usermodel.Workbook;
 import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
 
 /**
  * 数据导出默认实现
@@ -39,12 +44,11 @@ import org.apache.poi.xssf.streaming.SXSSFWorkbook;
  * @date 2024/5/9
  */
 @Slf4j
+@Component
+@RequiredArgsConstructor(onConstructor = @__(@Autowired))
 public class DefaultExportHandler implements ExportHandler {
     private final ExportProperties properties;
-
-    public DefaultExportHandler(@NonNull ExportProperties properties) {
-        this.properties = properties;
-    }
+    private final RedisTemplate<String, Object> redisTemplate;
 
     /**
      * 清理导出文件
@@ -71,7 +75,7 @@ public class DefaultExportHandler implements ExportHandler {
      */
     private void clear(List<File> files) {
         List<String> keys = files.stream().map(File::getName).map(this::key).collect(Collectors.toList());
-        List<?> values = RedisContextHolder.getRedisTemplate().opsForValue().multiGet(keys);
+        List<?> values = this.redisTemplate.opsForValue().multiGet(keys);
         if (ObjectUtils.notEmpty(values)) {
             for (int i = 0; i < values.size(); i++) {
                 if (Objects.isNull(values.get(i))) {
@@ -91,7 +95,34 @@ public class DefaultExportHandler implements ExportHandler {
         return "exporting:" + id;
     }
 
-    @Override
+    /**
+     * 获取任务状态
+     *
+     * @param id 任务ID
+     * @return 任务状态信息
+     */
+    private Pair<String, Boolean> pair(Serializable id) {
+        String value = (String) this.redisTemplate.opsForValue().get(this.key(id));
+        if (StringUtils.isEmpty(value)) {
+            return null;
+        }
+        String[] splits = value.split(":");
+        return Pair.of(splits[0], Boolean.valueOf(splits[1]));
+    }
+
+    /**
+     * 更新任务状态
+     *
+     * @param id       任务ID
+     * @param pair     任务状态信息
+     * @param duration 有效时间
+     */
+    private void pair(Serializable id, Pair<String, Boolean> pair, Duration duration) {
+        String value = pair.getLeft() + ":" + pair.getRight();
+        this.redisTemplate.opsForValue().set(this.key(id), value, duration);
+    }
+
+    @PostConstruct
     public void initialize() {
         ThreadUtils.run(() -> {
             while (!Thread.currentThread().isInterrupted()) {
@@ -107,17 +138,17 @@ public class DefaultExportHandler implements ExportHandler {
 
     @Override
     public boolean isCompleted(long id) {
-        Pair<?, ?> pair = (Pair<?, ?>) RedisContextHolder.getRedisTemplate().opsForValue().get(this.key(id));
-        return Boolean.TRUE.equals(ObjectUtils.ifNull(pair, Pair::getRight));
+        Boolean completed = ObjectUtils.ifNull(this.pair(id), Pair::getRight);
+        return Boolean.TRUE.equals(completed);
     }
 
     @Override
     public void download(long id, @NonNull HttpServletResponse response) throws IOException {
-        Pair<?, ?> pair = (Pair<?, ?>) RedisContextHolder.getRedisTemplate().opsForValue().get(this.key(id));
+        Pair<String, Boolean> pair = this.pair(id);
         AssertUtils.available(pair, () -> ApplicationContextHolder.getMessage("Export.Expired"));
         boolean completed = Boolean.TRUE.equals(ObjectUtils.ifNull(pair, Pair::getRight));
         AssertUtils.available(completed, () -> ApplicationContextHolder.getMessage("Export.Uncompleted"));
-        String filename = (String) ObjectUtils.ifNull(pair, Pair::getLeft);
+        String filename = ObjectUtils.ifNull(pair, Pair::getLeft);
         HttpUtils.write(response, new File(this.properties.getDirectory(), String.valueOf(id)), filename);
     }
 
@@ -129,8 +160,7 @@ public class DefaultExportHandler implements ExportHandler {
         long id = RedisContextHolder.identity();
 
         // 初始化数据导出状态
-        String key = this.key(id);
-        RedisContextHolder.getRedisTemplate().opsForValue().set(key, Pair.of(filename, false), Duration.ofDays(1));
+        this.pair(id, Pair.of(filename, false), Duration.ofDays(1));
 
         // 异步执行导出任务
         ThreadContextHolder.execute(() -> {
@@ -148,8 +178,7 @@ public class DefaultExportHandler implements ExportHandler {
             }
 
             // 更新数据导出任务状态
-            Duration duration = Duration.ofSeconds(this.properties.getExpiration());
-            RedisContextHolder.getRedisTemplate().opsForValue().set(key, Pair.of(filename, true), duration);
+            this.pair(id, Pair.of(filename, true), Duration.ofSeconds(this.properties.getExpiration()));
 
             // 数据导出完成监听回调
             listener.accept(id, volume);

+ 0 - 12
framework-export/src/main/java/com/chelvc/framework/export/ExportHandler.java

@@ -67,16 +67,4 @@ public interface ExportHandler {
     <T> long export(String filename, BiConsumer<Long, Integer> listener,
                     BiFunction<Integer, Integer, Collection<T>> provider, ExcelUtils.Writer<T> writer,
                     String... titles);
-
-    /**
-     * 初始化处理器
-     */
-    default void initialize() {
-    }
-
-    /**
-     * 销毁处理器
-     */
-    default void destroy() {
-    }
 }

+ 0 - 25
framework-export/src/main/java/com/chelvc/framework/export/config/ExportConfigurer.java

@@ -1,25 +0,0 @@
-package com.chelvc.framework.export.config;
-
-import com.chelvc.framework.export.ExportHandler;
-import com.chelvc.framework.export.support.DefaultExportHandler;
-import lombok.RequiredArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-/**
- * 数据导出配置
- *
- * @author Woody
- * @date 2024/5/10
- */
-@Configuration
-@RequiredArgsConstructor(onConstructor = @__(@Autowired))
-public class ExportConfigurer {
-    private final ExportProperties properties;
-
-    @Bean(initMethod = "initialize", destroyMethod = "destroy")
-    public ExportHandler exportHandler() {
-        return new DefaultExportHandler(this.properties);
-    }
-}

+ 2 - 1
framework-security/src/main/java/com/chelvc/framework/security/interceptor/SecurityExceptionInterceptor.java

@@ -2,6 +2,7 @@ package com.chelvc.framework.security.interceptor;
 
 import javax.servlet.http.HttpServletRequest;
 
+import com.chelvc.framework.base.context.ApplicationContextHolder;
 import com.chelvc.framework.base.context.LoggingContextHolder;
 import com.chelvc.framework.base.context.Result;
 import com.chelvc.framework.base.context.SessionContextHolder;
@@ -35,6 +36,6 @@ public class SecurityExceptionInterceptor {
     @ExceptionHandler(AccessDeniedException.class)
     public Result<?> exception(HttpServletRequest request, AccessDeniedException e) {
         LoggingContextHolder.warn(log, request, e);
-        return SessionContextHolder.result(HttpStatus.FORBIDDEN, e.getMessage());
+        return SessionContextHolder.result(HttpStatus.FORBIDDEN, ApplicationContextHolder.getMessage("Forbidden"));
     }
 }

+ 6 - 6
framework-upload/src/main/java/com/chelvc/framework/upload/UploadHandler.java

@@ -11,6 +11,12 @@ import java.io.InputStream;
  * @date 2024/1/30
  */
 public interface UploadHandler {
+    /**
+     * 初始化处理器
+     */
+    default void initialize() {
+    }
+
     /**
      * 文件上传
      *
@@ -41,12 +47,6 @@ public interface UploadHandler {
      */
     String upload(InputStream stream, String suffix, long length) throws IOException;
 
-    /**
-     * 初始化处理器
-     */
-    default void initialize() {
-    }
-
     /**
      * 销毁处理器
      */

+ 10 - 0
framework-upload/src/main/java/com/chelvc/framework/upload/support/DelegatingUploadHandler.java

@@ -64,6 +64,11 @@ public class DelegatingUploadHandler implements UploadHandler {
         return null;
     }
 
+    @Override
+    public void initialize() {
+        this.handlers.forEach(UploadHandler::initialize);
+    }
+
     @Override
     public String upload(@NonNull File file) throws IOException {
         return this.execute(handler -> handler.upload(file));
@@ -78,4 +83,9 @@ public class DelegatingUploadHandler implements UploadHandler {
     public String upload(@NonNull InputStream stream, String suffix, long length) throws IOException {
         return this.execute(handler -> handler.upload(stream, suffix, length));
     }
+
+    @Override
+    public void destroy() {
+        this.handlers.forEach(UploadHandler::destroy);
+    }
 }