|
@@ -1,25 +1,32 @@
|
|
|
package com.abi.qms.platform.infrastructure.mq;
|
|
|
|
|
|
+import cn.hutool.core.io.FileUtil;
|
|
|
import cn.hutool.core.io.file.FileWriter;
|
|
|
import cn.hutool.core.util.ZipUtil;
|
|
|
-import com.abi.qms.platform.dao.entity.QrData;
|
|
|
-import com.abi.qms.platform.dao.entity.QrInnerData;
|
|
|
-import com.abi.qms.platform.dao.entity.QrPackage;
|
|
|
-import com.abi.qms.platform.dao.entity.QrRepertorySerialNumber;
|
|
|
+import com.abi.qms.platform.dao.entity.*;
|
|
|
import com.abi.qms.platform.dao.enums.QrFormatUrlEnum;
|
|
|
import com.abi.qms.platform.dao.enums.QrPackageGenerateStatusEnum;
|
|
|
import com.abi.qms.platform.dao.enums.QrRepertoryTypeEnum;
|
|
|
+import com.abi.qms.platform.dao.mapper.QrPackageBatchMapper;
|
|
|
import com.abi.qms.platform.dao.mapper.QrPackageMapper;
|
|
|
import com.abi.qms.platform.dao.mapper.QrRepertoryMapper;
|
|
|
import com.abi.qms.platform.dao.mapper.QrRepertorySerialNumberMapper;
|
|
|
+import com.abi.qms.platform.dao.tablestore.entity.QrCode;
|
|
|
import com.abi.qms.platform.dao.vo.result.QrPackageVO;
|
|
|
import com.abi.qms.platform.dao.vo.result.QrRepertoryColumnVO;
|
|
|
import com.abi.qms.platform.dao.vo.result.QrRepertoryVO;
|
|
|
import com.abi.qms.platform.infrastructure.qr.build.parent.SerialBuildCode;
|
|
|
import com.abi.qms.platform.infrastructure.util.BuildCodeUtil;
|
|
|
-import com.abi.qms.platform.service.QrDataService;
|
|
|
import com.abi.qms.platform.service.QrPackageService;
|
|
|
+import com.abi.task.common.tablestore.TableStorePlusUtils;
|
|
|
+import com.abi.task.common.tablestore.common.TableStoreEntity;
|
|
|
+import com.abi.task.common.tablestore.entity.DemoEntity;
|
|
|
+import com.abi.task.common.utils.TableStoreUtils;
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.alicloud.openservices.tablestore.model.search.query.BoolQuery;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|
|
import com.rabbitmq.client.Channel;
|
|
|
import lombok.SneakyThrows;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
@@ -33,9 +40,15 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.messaging.Message;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
+import net.lingala.zip4j.core.ZipFile;
|
|
|
+import net.lingala.zip4j.exception.ZipException;
|
|
|
+import net.lingala.zip4j.model.ZipParameters;
|
|
|
+import net.lingala.zip4j.util.Zip4jConstants;
|
|
|
|
|
|
import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
@@ -61,8 +74,8 @@ public class GenerateCodeConsumer {
|
|
|
@Autowired
|
|
|
private QrRepertorySerialNumberMapper qrRepertorySerialNumberMapper;
|
|
|
|
|
|
- @Autowired
|
|
|
- private QrDataService qrDataService;
|
|
|
+// @Autowired
|
|
|
+// private QrDataService qrDataService;
|
|
|
|
|
|
@Autowired
|
|
|
private QrPackageService qrPackageService;
|
|
@@ -70,6 +83,21 @@ public class GenerateCodeConsumer {
|
|
|
@Autowired
|
|
|
private RedissonClient redissonClient;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private TableStorePlusUtils tableStorePlusUtils;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private QrPackageBatchMapper qrPackageBatchMapper;
|
|
|
+
|
|
|
+ //生成码数据
|
|
|
+ final List<QrData> qrDataList = new LinkedList<>();
|
|
|
+
|
|
|
+ //生成码包路径
|
|
|
+ private File file = new File(this.getClass().getResource("/").getPath()+"/code");
|
|
|
+
|
|
|
+ //批量添加文件
|
|
|
+ private ArrayList<File> files = new ArrayList<>();
|
|
|
+
|
|
|
/** 允许单个码生成重复的次数 */
|
|
|
private static final int REPEAT_BUILD_CODE_TIMES = 10;
|
|
|
|
|
@@ -82,7 +110,8 @@ public class GenerateCodeConsumer {
|
|
|
|
|
|
@SneakyThrows
|
|
|
@RabbitHandler
|
|
|
- public void onMessage(QrPackage qrPackage, Message message, Channel channel) {
|
|
|
+ public void onMessage(String objeQrPackage, Message message, Channel channel) {
|
|
|
+ QrPackage qrPackage = JSONObject.parseObject(objeQrPackage,QrPackage.class);
|
|
|
try {
|
|
|
// 生成码
|
|
|
loopGenerateCode(qrPackage);
|
|
@@ -126,48 +155,99 @@ public class GenerateCodeConsumer {
|
|
|
// child_index用于标记同一列的第几个码格式变量
|
|
|
Map<String, QrRepertorySerialNumber> qrRepertorySerialNumberMap = new LinkedHashMap<>();
|
|
|
|
|
|
- // 处理url和流水号
|
|
|
+ // 处理url和流水号--后续生成码要用到
|
|
|
getUrlAndSerialNumber(qrRepertoryColumnList, qrRepertoryId, deptUrl, urlMap, qrRepertorySerialNumberMap);
|
|
|
|
|
|
- // 申请数量、批次号、创建时间、重复次数
|
|
|
- Long qrNumber = qrPackageVo.getQrNumber();
|
|
|
-// String batchNumber = qrPackageVo.getBatchNumber();
|
|
|
- LocalDateTime localDateTime = LocalDateTime.now();
|
|
|
- int repeatTimes = 0;
|
|
|
-
|
|
|
- // 循环生成码
|
|
|
-// loopGenerateCode(qrRepertoryColumnList, qrRepertoryId, urlMap, qrRepertorySerialNumberMap, qrNumber, batchNumber, localDateTime, repeatTimes);
|
|
|
-
|
|
|
- // 更新码库流水号
|
|
|
- if (!qrRepertorySerialNumberMap.isEmpty()) {
|
|
|
- for (Map.Entry<String, QrRepertorySerialNumber> entry : qrRepertorySerialNumberMap.entrySet()) {
|
|
|
- QrRepertorySerialNumber qrRepertorySerialNumber = entry.getValue();
|
|
|
- QrRepertorySerialNumber updateSerialNumber = new QrRepertorySerialNumber()
|
|
|
- .setId(qrRepertorySerialNumber.getId())
|
|
|
- .setSerialNumber(qrRepertorySerialNumber.getSerialNumber());
|
|
|
- qrRepertorySerialNumberMapper.updateById(updateSerialNumber);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 创建码文件
|
|
|
- createCodeFile(qrPackage, qrRepertory);
|
|
|
+ //码包id
|
|
|
+ //根据码包id查询,获取批次号
|
|
|
+ QueryWrapper<QrPackageBatch> param = new QueryWrapper<>();
|
|
|
+ param.eq("package_id", qrPackageVo.getId());
|
|
|
+ List<QrPackageBatch> qrPackageBatches = qrPackageBatchMapper.selectList(param);
|
|
|
+
|
|
|
+ for (QrPackageBatch qrPackageBatch:qrPackageBatches) {
|
|
|
+ // 这批下的申请数量
|
|
|
+ Long qrNumber = qrPackageBatch.getBatchQrNumber();
|
|
|
+ //批次号
|
|
|
+ String batchNumber = qrPackageBatch.getBatchNumber();
|
|
|
+ //重复次数
|
|
|
+ int repeatTimes = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * qrRepertoryColumnList 码库的列
|
|
|
+ * qrRepertoryId 码库id
|
|
|
+ * urlMap 存放每列的url
|
|
|
+ * qrRepertorySerialNumberMap 用于标记同一列的第几个码格式变量
|
|
|
+ * qrNumber 码数量
|
|
|
+ * batchNumber 批次号
|
|
|
+ * localDateTime 创建时间
|
|
|
+ */
|
|
|
+ // 循环生成码
|
|
|
+ List<QrData> codeList = loopGenerateCode(qrRepertoryColumnList, qrRepertoryId, urlMap, qrRepertorySerialNumberMap, qrNumber, batchNumber, repeatTimes);
|
|
|
+
|
|
|
+ // table数据库 批量插入
|
|
|
+ saveTableStore(qrPackageBatch, codeList);
|
|
|
+
|
|
|
+ // 创建码文件
|
|
|
+ createCodeFile(qrRepertory,batchNumber);
|
|
|
|
|
|
+ }
|
|
|
// 更改生成状态为已生成
|
|
|
qrPackageUpdate = new QrPackage().setId(qrPackageVo.getId()).setGenerateStatus(QrPackageGenerateStatusEnum.GENERATE_SUCCESS.getCode());
|
|
|
qrPackageMapper.updateById(qrPackageUpdate);
|
|
|
+ //压缩后得名字
|
|
|
+ String zipName = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now())+".zip";
|
|
|
+// 压缩密码
|
|
|
+ String pas = String.valueOf((int) (Math.random()*9+1)*100000);
|
|
|
+ log.info("生成密码:"+pas);
|
|
|
+ //压缩加密文件
|
|
|
+ zipEncryption(file,files,pas,zipName);
|
|
|
+ // TODO:上传阿里云,并更新码包的下载路径 保存zip密码
|
|
|
+
|
|
|
+ //删除生成文件
|
|
|
+ FileUtil.del(file);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 循环生成码
|
|
|
+ * 批量新增tableStore,码表
|
|
|
*/
|
|
|
- private void loopGenerateCode(List<QrRepertoryColumnVO> qrRepertoryColumnList, Long qrRepertoryId, Map<Long, String> urlMap, Map<String, QrRepertorySerialNumber> qrRepertorySerialNumberMap, Long qrNumber, String batchNumber, LocalDateTime localDateTime, int repeatTimes) {
|
|
|
- // 生成码
|
|
|
- while (true) {
|
|
|
- // 查询已生成的数量
|
|
|
- long alreadyGenerateNumber = qrDataService.selectCountByBatchNumber(batchNumber);
|
|
|
+ private void saveTableStore(QrPackageBatch qrPackageBatch, List<QrData> codeList) {
|
|
|
+ List<TableStoreEntity> codeSave = new ArrayList<>();
|
|
|
+ for (QrData qrData:codeList) {
|
|
|
+ List<QrInnerData> innerDataList = qrData.getInnerDataList();
|
|
|
+ for (QrInnerData qrInnerData:innerDataList) {
|
|
|
+ QrCode qrCode = new QrCode();
|
|
|
+ qrCode.setId(String.valueOf(IdWorker.getId()));
|
|
|
+ //码
|
|
|
+ qrCode.setCode(qrInnerData.getCode());
|
|
|
+ //批次id
|
|
|
+ qrCode.setBatchNumberId(qrPackageBatch.getId());
|
|
|
+ //码包id
|
|
|
+ qrCode.setPackageId(qrPackageBatch.getPackageId());
|
|
|
+ //要拼接的url
|
|
|
+ qrCode.setUrl(qrInnerData.getUrl());
|
|
|
+ //创建时间
|
|
|
+ qrCode.setCreateTime(LocalDateTime.now());
|
|
|
+ codeSave.add(qrCode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tableStorePlusUtils.putRow(codeSave);
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * qrRepertoryColumnList 码库的列
|
|
|
+ * qrRepertoryId 码库id
|
|
|
+ * urlMap 存放每列的url
|
|
|
+ * qrRepertorySerialNumberMap 用于标记同一列的第几个码格式变量
|
|
|
+ * qrNumber 码数量
|
|
|
+ * batchNumber 批次号
|
|
|
+ * localDateTime 创建时间
|
|
|
+ * repeatTimes 失败次数
|
|
|
+ */
|
|
|
+ private List<QrData> loopGenerateCode(List<QrRepertoryColumnVO> qrRepertoryColumnList, Long qrRepertoryId, Map<Long, String> urlMap, Map<String, QrRepertorySerialNumber> qrRepertorySerialNumberMap, Long qrNumber, String batchNumber, int repeatTimes) {
|
|
|
+ LocalDateTime localDateTime = LocalDateTime.now();
|
|
|
+ while (true) {
|
|
|
// 计算还需生成的数量
|
|
|
- long needGenerateNumber = qrNumber - alreadyGenerateNumber;
|
|
|
+ long needGenerateNumber = qrNumber --;
|
|
|
|
|
|
if (needGenerateNumber <= 0) {
|
|
|
log.info("批次号:{},码生成完毕", batchNumber);
|
|
@@ -177,7 +257,6 @@ public class GenerateCodeConsumer {
|
|
|
// 计算本次最多生成多少码
|
|
|
long currentMaxGenerateNumber = needGenerateNumber <= ONCE_GENERATE_NUMBER ? needGenerateNumber : ONCE_GENERATE_NUMBER;
|
|
|
|
|
|
- List<QrData> qrDataList = new LinkedList<>();
|
|
|
// 用Set存放不重复的码
|
|
|
HashSet<String> uniqueSet = new HashSet<>();
|
|
|
// 生成码要用的参数
|
|
@@ -222,19 +301,18 @@ public class GenerateCodeConsumer {
|
|
|
|
|
|
qrData.setInnerDataList(qrInnerDataList);
|
|
|
qrDataList.add(qrData);
|
|
|
-
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
- qrDataService.batchInsert(qrDataList);
|
|
|
+ return qrDataList;
|
|
|
} catch (Exception e) {
|
|
|
- // mongoDB唯一索引冲突导致插入失败,继续生成码
|
|
|
- log.error("mongo insert error", e);
|
|
|
+ log.error("封装码失败", e);
|
|
|
if (++repeatTimes >= REPEAT_BUILD_CODE_TIMES) {
|
|
|
throw new RuntimeException("生成码失败,重复生成码次数超过" + REPEAT_BUILD_CODE_TIMES + "次");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -299,15 +377,12 @@ public class GenerateCodeConsumer {
|
|
|
/**
|
|
|
* 创建码文件
|
|
|
*/
|
|
|
- private void createCodeFile(QrPackage qrPackage, QrRepertoryVO qrRepertory) {
|
|
|
- String batchNumber = qrPackage.getBatchNumber();
|
|
|
- List<QrData> qrDataList = qrDataService.selectCodeByBatch(batchNumber);
|
|
|
+ private void createCodeFile( QrRepertoryVO qrRepertory,String batchNumber) {
|
|
|
List<QrRepertoryColumnVO> qrRepertoryColumnList = qrRepertory.getQrRepertoryColumnList();
|
|
|
StringBuilder content = new StringBuilder();
|
|
|
// 第一行为每列的名称,用“,”分隔
|
|
|
String dataComposition = qrRepertoryColumnList.stream().map(col -> col.getAlias()).collect(Collectors.joining(","));
|
|
|
content.append(dataComposition).append("\r\n");
|
|
|
-
|
|
|
// 拼接码
|
|
|
List<QrInnerData> innerDataList;
|
|
|
String innerData;
|
|
@@ -316,16 +391,19 @@ public class GenerateCodeConsumer {
|
|
|
innerData = innerDataList.stream().map(qrInnerData -> qrInnerData.getUrl() + qrInnerData.getCode()).collect(Collectors.joining(","));
|
|
|
content.append(innerData).append("\r\n");
|
|
|
}
|
|
|
+ //如果文件不存在,创建一个文件
|
|
|
+ try{
|
|
|
+ if (!file.exists()) {
|
|
|
+ file.mkdir();
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ log.error("创建文件异常",e);
|
|
|
+ }
|
|
|
|
|
|
- // 生成txt和zip文件
|
|
|
- FileWriter fileWriter = new FileWriter(batchNumber + ".txt");
|
|
|
+ // 生成txt
|
|
|
+ FileWriter fileWriter = new FileWriter(file.getPath()+"/"+ batchNumber + ".txt");
|
|
|
fileWriter.write(content.toString());
|
|
|
- File txtFile = fileWriter.getFile();
|
|
|
- File zipFile = ZipUtil.zip(txtFile);
|
|
|
-
|
|
|
- // 删除生成的临时文件,上传阿里云,并更新码包的下载路径
|
|
|
- qrPackageService.delFileAndUpdatePath(txtFile, zipFile, qrPackage.getId());
|
|
|
-
|
|
|
+ files.add(new File(file.getPath()+"/"+ batchNumber + ".txt"));
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -376,4 +454,46 @@ public class GenerateCodeConsumer {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * zip加密
|
|
|
+ * @param file
|
|
|
+ * @param files txt文件
|
|
|
+ * @param pas 密码
|
|
|
+ * @param zipName 压缩后的名字
|
|
|
+ */
|
|
|
+ private void zipEncryption(File file ,ArrayList<File> files,String pas,String zipName){
|
|
|
+ try {
|
|
|
+ //创建压缩文件
|
|
|
+ ZipFile zipFile = new ZipFile(file.getPath()+"/"+zipName);
|
|
|
+ //设置压缩文件参数
|
|
|
+ ZipParameters parameters = new ZipParameters();
|
|
|
+ //设置压缩方法
|
|
|
+ parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
|
|
|
+
|
|
|
+ //设置压缩级别
|
|
|
+ //DEFLATE_LEVEL_FASTEST - Lowest compression level but higher speed of compression
|
|
|
+ //DEFLATE_LEVEL_FAST - Low compression level but higher speed of compression
|
|
|
+ //DEFLATE_LEVEL_NORMAL - Optimal balance between compression level/speed
|
|
|
+ //DEFLATE_LEVEL_MAXIMUM - High compression level with a compromise of speed
|
|
|
+ //DEFLATE_LEVEL_ULTRA - Highest compression level but low speed
|
|
|
+ parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
|
|
|
+
|
|
|
+ //设置压缩文件加密
|
|
|
+ parameters.setEncryptFiles(true);
|
|
|
+
|
|
|
+ //设置加密方法
|
|
|
+ parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
|
|
|
+
|
|
|
+ //设置aes加密强度
|
|
|
+ parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
|
|
|
+
|
|
|
+ //设置密码
|
|
|
+ parameters.setPassword(pas);
|
|
|
+
|
|
|
+ //添加文件到压缩文件
|
|
|
+ zipFile.addFiles(files, parameters);
|
|
|
+ } catch (ZipException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|