导入导出通用实现
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.bean.BeanUtil;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
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.BeanSearcher;
|
||||||
import cn.zhxu.bs.SearchResult;
|
import cn.zhxu.bs.SearchResult;
|
||||||
import cn.zhxu.bs.operator.Contain;
|
import cn.zhxu.bs.operator.Contain;
|
||||||
import cn.zhxu.bs.util.MapUtils;
|
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.constant.GlobalConstants;
|
||||||
import com.example.demo.common.domain.BaseDTO;
|
import com.example.demo.common.domain.BaseDTO;
|
||||||
import com.example.demo.common.domain.BaseEntity;
|
import com.example.demo.common.domain.BaseEntity;
|
||||||
import com.example.demo.common.domain.BaseQueryDTO;
|
import com.example.demo.common.domain.BaseQueryDTO;
|
||||||
import com.example.demo.common.domain.BaseVO;
|
import com.example.demo.common.domain.BaseVO;
|
||||||
|
import com.example.demo.common.exception.BusinessException;
|
||||||
import com.fhs.trans.service.impl.TransService;
|
import com.fhs.trans.service.impl.TransService;
|
||||||
import com.mybatisflex.core.BaseMapper;
|
import com.mybatisflex.core.BaseMapper;
|
||||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import jakarta.annotation.PreDestroy;
|
import jakarta.annotation.PreDestroy;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
@ -24,8 +30,12 @@ import org.springframework.beans.factory.InitializingBean;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -59,6 +69,9 @@ public abstract class BaseServiceImpl<
|
|||||||
/** 实际业务实现VO类 */
|
/** 实际业务实现VO类 */
|
||||||
private final Class<VO> clazzVO;
|
private final Class<VO> clazzVO;
|
||||||
|
|
||||||
|
/** 实际业务实现Entity类 */
|
||||||
|
private final Class<Entity> clazzEntity;
|
||||||
|
|
||||||
/** 提供Select服务 */
|
/** 提供Select服务 */
|
||||||
private final BeanSearcher beanSearcher;
|
private final BeanSearcher beanSearcher;
|
||||||
|
|
||||||
@ -164,12 +177,160 @@ public abstract class BaseServiceImpl<
|
|||||||
return wordVO;
|
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
|
@Override
|
||||||
public void refreshCache() {
|
public void refreshCache() {
|
||||||
// ignore
|
// ignore
|
||||||
log.warn("刷新缓存(暂无实现)");
|
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
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
// ignore
|
// ignore
|
||||||
@ -270,4 +431,29 @@ public abstract class BaseServiceImpl<
|
|||||||
ParameterizedType parameterizedType = (ParameterizedType) superClass;
|
ParameterizedType parameterizedType = (ParameterizedType) superClass;
|
||||||
return (Class<DTO>) parameterizedType.getActualTypeArguments()[2];
|
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,
|
BeanSearcher beanSearcher,
|
||||||
TransService transService
|
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,
|
BeanSearcher beanSearcher,
|
||||||
TransService transService
|
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,
|
BeanSearcher beanSearcher,
|
||||||
TransService transService
|
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,
|
BeanSearcher beanSearcher,
|
||||||
TransService transService
|
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,
|
BeanSearcher beanSearcher,
|
||||||
TransService transService
|
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,
|
BeanSearcher beanSearcher,
|
||||||
TransService transService
|
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,
|
BeanSearcher beanSearcher,
|
||||||
TransService transService
|
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,
|
BeanSearcher beanSearcher,
|
||||||
TransService transService
|
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