导入导出通用实现
This commit is contained in:
parent
091b281544
commit
4f6b03cd53
@ -3,20 +3,26 @@ package com.example.demo.common.typography;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.core.util.ZipUtil;
|
||||
import cn.zhxu.bs.BeanSearcher;
|
||||
import cn.zhxu.bs.SearchResult;
|
||||
import cn.zhxu.bs.operator.Contain;
|
||||
import cn.zhxu.bs.util.MapUtils;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.example.demo.common.constant.GlobalConstants;
|
||||
import com.example.demo.common.domain.BaseDTO;
|
||||
import com.example.demo.common.domain.BaseEntity;
|
||||
import com.example.demo.common.domain.BaseQueryDTO;
|
||||
import com.example.demo.common.domain.BaseVO;
|
||||
import com.example.demo.common.exception.BusinessException;
|
||||
import com.fhs.trans.service.impl.TransService;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@ -24,8 +30,12 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -59,6 +69,9 @@ public abstract class BaseServiceImpl<
|
||||
/** 实际业务实现VO类 */
|
||||
private final Class<VO> clazzVO;
|
||||
|
||||
/** 实际业务实现Entity类 */
|
||||
private final Class<Entity> clazzEntity;
|
||||
|
||||
/** 提供Select服务 */
|
||||
private final BeanSearcher beanSearcher;
|
||||
|
||||
@ -164,12 +177,160 @@ public abstract class BaseServiceImpl<
|
||||
return wordVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object importDetail(String line) {
|
||||
log.warn("导入细节(暂无实现)");
|
||||
JSONObject jsonObject = JSON.parseObject(line);
|
||||
jsonObject.get("ts");
|
||||
jsonObject.get("");
|
||||
Entity entity = JSON.parseObject(line, clazzEntity);
|
||||
Map<String, String> result = new HashMap<>();
|
||||
|
||||
// 默认导入失败
|
||||
result.put("state", "error");
|
||||
if(ObjectUtil.isNotEmpty(detail(entity.getId()))) {
|
||||
result.put("id", entity.getId());
|
||||
if(StrUtil.isNotBlank(entity.getName())) {
|
||||
result.put("name", entity.getName());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO 解密,校验完整性
|
||||
|
||||
// 设置默认值
|
||||
if (entity.getIsDeleted() == null) {
|
||||
entity.setIsDeleted(Integer.valueOf(GlobalConstants.N));
|
||||
}
|
||||
|
||||
// 保存到数据库
|
||||
boolean flag = save(entity);
|
||||
if (flag) {
|
||||
result.put("state", "success");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object exportDetail(String id) {
|
||||
log.warn("导出细节(暂无实现)");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshCache() {
|
||||
// ignore
|
||||
log.warn("刷新缓存(暂无实现)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> importJSONLData(String content) {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
int successCount = 0;
|
||||
int failCount = 0;
|
||||
List<String> errors = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// 按行分割JSONL数据
|
||||
String[] lines = content.split("\n");
|
||||
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
String line = lines[i].trim();
|
||||
if (line.isEmpty()) continue;
|
||||
|
||||
try {
|
||||
// 解析每一行JSON为Entity对象
|
||||
// 使用try-catch块忽略无法转化的数据,继续处理下一行
|
||||
importDetail(line);
|
||||
successCount++;
|
||||
} catch (Exception e) {
|
||||
// 记录失败信息但继续处理下一行数据
|
||||
failCount++;
|
||||
errors.add("第" + (i + 1) + "行导入失败: " + e.getMessage());
|
||||
log.warn("忽略无法解析的JSON数据行[{}]: {}", i + 1, line);
|
||||
// 继续处理下一行,不抛出异常中断整体流程
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.put("successCount", String.valueOf(successCount));
|
||||
result.put("failCount", String.valueOf(failCount));
|
||||
result.put("errors", String.join("\n", errors));
|
||||
result.put("message", "导入完成,成功 " + successCount + " 条,失败 " + failCount + " 条");
|
||||
|
||||
} catch (Exception e) {
|
||||
result.put("error", "解析JSONL数据失败: " + e.getMessage());
|
||||
result.put("successCount", "0");
|
||||
result.put("failCount", "0");
|
||||
result.put("message", "导入失败");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exportJSONLData(HttpServletResponse response, List<String> ids) {
|
||||
try {
|
||||
if (ids == null || ids.isEmpty()) {
|
||||
throw new BusinessException("导出ID列表不能为空");
|
||||
}
|
||||
|
||||
// 验证并获取所有要导出的数据
|
||||
List<Object> list = new ArrayList<>();
|
||||
for (String id : ids) {
|
||||
try {
|
||||
// 使用detail方法验证ID是否存在,并获取数据
|
||||
Object templateVO = exportDetail(id);
|
||||
if (templateVO == null) {
|
||||
throw new BusinessException("不存在: " + id);
|
||||
}
|
||||
// 添加到导出列表
|
||||
list.add(templateVO);
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
// 准备文件流和文件名列表用于压缩
|
||||
List<String> fileNameUniqueList = new ArrayList<>();
|
||||
List<InputStream> inputStreams = new ArrayList<>();
|
||||
|
||||
// 创建一个JSONL文件,包含所有模板数据,每行一个JSON对象
|
||||
StringBuilder jsonlContent = new StringBuilder();
|
||||
for (Object object : list) {
|
||||
String jsonContent = JSON.toJSONString(object);
|
||||
// TODO 加密
|
||||
jsonlContent.append(jsonContent).append("\n");
|
||||
}
|
||||
// 转换为数组
|
||||
String[] fileNamesArr = fileNameUniqueList.toArray(new String[0]);
|
||||
InputStream[] inputStreamsArr = inputStreams.toArray(new InputStream[0]);
|
||||
|
||||
// 使用ZipUtil进行压缩下载
|
||||
try {
|
||||
ZipUtil.zip(response.getOutputStream(), fileNamesArr, inputStreamsArr);
|
||||
} catch (IOException e) {
|
||||
throw new BusinessException("压缩下载失败: " + e.getMessage());
|
||||
} finally {
|
||||
// 关闭所有输入流
|
||||
for (InputStream inputStream : inputStreams) {
|
||||
try {
|
||||
if (inputStream != null) {
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// 忽略关闭流的异常
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (BusinessException e) {
|
||||
// 直接抛出业务异常,保留原始错误信息
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException("导出JSONL数据失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// ignore
|
||||
@ -270,4 +431,29 @@ public abstract class BaseServiceImpl<
|
||||
ParameterizedType parameterizedType = (ParameterizedType) superClass;
|
||||
return (Class<DTO>) parameterizedType.getActualTypeArguments()[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* 确保密钥字节数组为指定长度
|
||||
* @param key 原始密钥字符串
|
||||
* @param length 所需长度
|
||||
* @return 调整后的密钥字节数组
|
||||
*/
|
||||
private static byte[] ensureKeyLength(String key, int length) {
|
||||
byte[] keyBytes = key.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
||||
if (keyBytes.length == length) {
|
||||
return keyBytes;
|
||||
} else if (keyBytes.length > length) {
|
||||
// 如果太长则截取
|
||||
byte[] result = new byte[length];
|
||||
System.arraycopy(keyBytes, 0, result, 0, length);
|
||||
return result;
|
||||
} else {
|
||||
// 如果太短则填充0(或者您可以选择其他填充方式)
|
||||
byte[] result = new byte[length];
|
||||
System.arraycopy(keyBytes, 0, result, 0, keyBytes.length);
|
||||
// 剩余部分默认为0
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -37,7 +37,11 @@ public class ConditionMapServiceImpl
|
||||
BeanSearcher beanSearcher,
|
||||
TransService transService
|
||||
) {
|
||||
super(log, ConditionMapServiceImpl.class.getSimpleName(), ConditionMapVO.class, beanSearcher, transService);
|
||||
super(log,
|
||||
ConditionMapServiceImpl.class.getSimpleName(),
|
||||
ConditionMapVO.class,
|
||||
ConditionMapEntity.class,
|
||||
beanSearcher, transService);
|
||||
}
|
||||
|
||||
}
|
@ -37,7 +37,11 @@ public class ConfigDocumentServiceImpl
|
||||
BeanSearcher beanSearcher,
|
||||
TransService transService
|
||||
) {
|
||||
super(log, ConfigDocumentServiceImpl.class.getSimpleName(), ConfigDocumentVO.class, beanSearcher, transService);
|
||||
super(log,
|
||||
ConfigDocumentServiceImpl.class.getSimpleName(),
|
||||
ConfigDocumentVO.class,
|
||||
ConfigDocumentEntity.class,
|
||||
beanSearcher, transService);
|
||||
}
|
||||
|
||||
}
|
@ -37,7 +37,11 @@ public class ConfigValueServiceImpl
|
||||
BeanSearcher beanSearcher,
|
||||
TransService transService
|
||||
) {
|
||||
super(log, ConfigValueServiceImpl.class.getSimpleName(), ConfigValueVO.class, beanSearcher, transService);
|
||||
super(log,
|
||||
ConfigValueServiceImpl.class.getSimpleName(),
|
||||
ConfigValueVO.class,
|
||||
ConfigValueEntity.class,
|
||||
beanSearcher, transService);
|
||||
}
|
||||
|
||||
}
|
@ -37,6 +37,10 @@ public class FileRecordServiceImpl
|
||||
BeanSearcher beanSearcher,
|
||||
TransService transService
|
||||
) {
|
||||
super(log, FileRecordServiceImpl.class.getSimpleName(), FileRecordVO.class, beanSearcher, transService);
|
||||
super(log,
|
||||
FileRecordServiceImpl.class.getSimpleName(),
|
||||
FileRecordVO.class,
|
||||
FileRecordEntity.class,
|
||||
beanSearcher, transService);
|
||||
}
|
||||
}
|
@ -37,7 +37,11 @@ public class LevelConfigServiceImpl
|
||||
BeanSearcher beanSearcher,
|
||||
TransService transService
|
||||
) {
|
||||
super(log, LevelConfigServiceImpl.class.getSimpleName(), LevelConfigVO.class, beanSearcher, transService);
|
||||
super(log,
|
||||
LevelConfigServiceImpl.class.getSimpleName(),
|
||||
LevelConfigVO.class,
|
||||
LevelConfigEntity.class,
|
||||
beanSearcher, transService);
|
||||
}
|
||||
|
||||
}
|
@ -38,7 +38,11 @@ public class MapperRuleServiceImpl
|
||||
BeanSearcher beanSearcher,
|
||||
TransService transService
|
||||
) {
|
||||
super(log, MapperRuleServiceImpl.class.getSimpleName(), MapperRuleVO.class, beanSearcher, transService);
|
||||
super(log,
|
||||
MapperRuleServiceImpl.class.getSimpleName(),
|
||||
MapperRuleVO.class,
|
||||
MapperRuleEntity.class,
|
||||
beanSearcher, transService);
|
||||
}
|
||||
|
||||
}
|
@ -38,7 +38,11 @@ public class ParseRuleServiceImpl
|
||||
BeanSearcher beanSearcher,
|
||||
TransService transService
|
||||
) {
|
||||
super(log, ParseRuleServiceImpl.class.getSimpleName(), ParseRuleVO.class, beanSearcher, transService);
|
||||
super(log,
|
||||
ParseRuleServiceImpl.class.getSimpleName(),
|
||||
ParseRuleVO.class,
|
||||
ParseRuleEntity.class,
|
||||
beanSearcher, transService);
|
||||
}
|
||||
|
||||
}
|
@ -37,7 +37,11 @@ public class ValueConfigServiceImpl
|
||||
BeanSearcher beanSearcher,
|
||||
TransService transService
|
||||
) {
|
||||
super(log, ValueConfigServiceImpl.class.getSimpleName(), ValueConfigVO.class, beanSearcher, transService);
|
||||
super(log,
|
||||
ValueConfigServiceImpl.class.getSimpleName(),
|
||||
ValueConfigVO.class,
|
||||
ValueConfigEntity.class,
|
||||
beanSearcher, transService);
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user