|
@@ -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);
|