package org.jeecg.modules.mdc.service.impl; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.file.FileReader; import cn.hutool.crypto.SmUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.jeecg.common.exception.JeecgBootException; import org.jeecg.modules.mdc.entity.LogTable; import org.jeecg.modules.mdc.mapper.LogTableMapper; import org.jeecg.modules.mdc.service.ILogTableService; import org.jeecg.modules.mdc.util.DateUtils; import org.jeecg.modules.mdc.util.FileClient; import org.jeecg.modules.mdc.util.SqlExecutor; import org.jeecg.modules.mdc.util.SyslogClient; import org.jeecg.modules.system.entity.MdcPassLog; import org.jeecg.modules.system.service.IMdcPassLogService; import org.jeecg.modules.system.util.FileUtils; import org.jeecg.modules.system.vo.SysLogTypeObjectDto; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.io.File; import java.net.InetAddress; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * @author Lius * @date 2024/12/18 14:29 */ @Service @Slf4j public class LogTableServiceImpl extends ServiceImpl implements ILogTableService { @Value("${fileService.localFilePath}") private String localFilePath; @Value("${fileService.servicePath}") private String servicePath; @Value("${fileService.host}") private String host; @Value("${fileService.port}") private String port; @Value("${fileService.username}") private String username; @Value("${fileService.pwd}") private String pwd; @Value("${fileService.addressToken}") private String addressToken; @Value("${fileService.addressUploadFile}") private String addressUploadFile; @Value("${fileService.logIp}") private String logIp; @Value("${fileService.logPort}") private String logPort; @Value("${fileService.newFilePath}") private String newFilePath; @Value("${fileService.failedLocFilePath}") private String failedLocFilePath; @Resource private IMdcPassLogService mdcPassLogService; private static final String TYPE = "18"; @Resource private SqlExecutor sqlExecutor; /** * 导出同步数据表sql到xml文件 */ @Override @Transactional(rollbackFor = Exception.class) public void exportDataToXml() { // step.1 查询最新数据 时间正序排列 List logTables = this.baseMapper.selectList(new LambdaQueryWrapper().orderByAsc(LogTable::getCreateTime)); if (logTables != null && !logTables.isEmpty()) { // step.2 处理数据 List sqlList = logTables.stream().map(LogTable::getSqlLog).collect(Collectors.toList()); // step.3 写入文件 // step.3.1 文件命名 String today = DateUtils.format(DateUtils.getNow(), DateUtils.STRDATE); MdcPassLog mdcPassLogLast = mdcPassLogService.selectTodayLast(today); int sequenceNumber = 1; if (mdcPassLogLast != null) { sequenceNumber = mdcPassLogLast.getSequenceNumber() + 1; } // 文件路径 String locFilePath = localFilePath + TYPE + today + String.format("%06d", sequenceNumber) + ".xml"; // FileWriter writer = new FileWriter(locFilePath); // writer.writeLines(sqlList); String listSql = String.join("\n", sqlList); try { FileUtils.fileWriterSql(locFilePath, listSql); } catch (Exception e) { throw new JeecgBootException("数据写入文件失败!"); } // step.4 推送网闸 // step.4.1 测试服务器连通性 /* boolean ping = NetUtil.ping(host + ":" + port); if (!ping) { FileUtil.del(locFilePath); throw new JeecgBootException("服务器连接: " + host + ":" + port + " 异常!"); }*/ // step.4.2 获取token String token = ""; try { token = FileClient.getToken(host, port, username, pwd, addressToken); } catch (Throwable e) { throw new JeecgBootException("获取token失败!"); } // step 4.3 调用文件上传接口 if (StringUtils.isNotBlank(token)) { try { File[] files = FileUtil.ls(localFilePath); for (File file : files) { if (file.isFile()) { SysLogTypeObjectDto objectName = new SysLogTypeObjectDto(); objectName.setDateTime(DateUtils.format(DateUtils.getNow(), DateUtils.STR_DATE_TIME_SMALL)); objectName.setFileName(file.getName()); objectName.setFileSize(FileUtils.changeFileFormatKb(String.valueOf(new File(localFilePath).length()))); objectName.setSourceAddress(localFilePath); String sm3 = SmUtil.sm3(file); objectName.setAbstract1(sm3); //顺序号 String fileName = file.getName(); String sequenceOrder = fileName.substring(fileName.length() - 10, fileName.length() - 4); String dayTime = fileName.substring(fileName.length() - 18, fileName.length() - 10); int sequenceNum = Integer.parseInt(sequenceOrder); objectName.setFileNum(Integer.toString(sequenceNum)); // 插入传输日志 MdcPassLog mdcPassLog = new MdcPassLog(); mdcPassLog.setPassLogFileName(file.getAbsolutePath()); mdcPassLog.setPassName(fileName); mdcPassLog.setDayTime(dayTime); mdcPassLog.setSequenceNumber(sequenceNum); mdcPassLog.setSequenceOrder(sequenceOrder); mdcPassLogService.save(mdcPassLog); String ip = InetAddress.getLocalHost().getHostAddress(); if (StringUtils.isBlank(ip)) { objectName.setSourceAddress("10.118.10.62"); objectName.setAddress("10.118.10.62"); } else { objectName.setSourceAddress(ip); objectName.setAddress(ip); } objectName.setDestination(host); objectName.setResult("失败"); // 本地文件路径 String loFilePath = localFilePath + file.getName(); // 目标文件路径 String servicePathName = servicePath + file.getName(); String result = FileClient.uploadFile(host, port, token, file.getName(), servicePathName, loFilePath, addressUploadFile); if ("成功".equals(result)) { if (sequenceNumber == 1) { // 删除昨日备份文件夹中历史文件 FileUtil.clean(newFilePath); } // 成功之后将文件备份走 FileUtil.move(new File(locFilePath), new File(newFilePath + fileName), true); // FileUtil.copy(locFilePath, newFilePath + fileName, true); // FileUtil.del(loFilePath); objectName.setResult("成功"); SyslogClient.sendClient(logIp, Integer.valueOf(logPort), objectName.toString()); } else { objectName.setResult(result); objectName.setTypes("error"); SyslogClient.sendClient(logIp, Integer.valueOf(logPort), objectName.toString()); } } } } catch (Throwable e) { throw new JeecgBootException("调用文件上传接口失败!"); } } // step.5 删除已经写入文件并发送至网闸的数据 // step.5.1 删除数据库数据 this.baseMapper.delete(new LambdaQueryWrapper().le(LogTable::getCreateTime, logTables.get(logTables.size() - 1).getCreateTime())); } } /** * 导入同步数据sql执行到数据库 */ @Override @Transactional(rollbackFor = Exception.class) public void importXmlToData() { File[] files = FileUtil.ls(localFilePath); List failedSqlList = new ArrayList<>(); // 用于存储执行失败的 SQL for (File file : files) { if (file.isFile()) { String loFilePath = localFilePath + file.getName(); FileReader fileReader = new FileReader(loFilePath); List sqlList = fileReader.readLines(); log.info("成功读取到{}条sql,执行操作", sqlList.size()); for (String sql : sqlList) { try { sqlExecutor.execute(sql); } catch (Exception e) { failedSqlList.add(sql); // throw new JeecgBootException("执行sql失败!"); } } if (!failedSqlList.isEmpty()) { try { FileUtil.appendLines(failedSqlList, failedLocFilePath, "UTF-8"); } catch (Exception e) { throw new JeecgBootException("数据写入文件失败!"); } } // String sqlList = fileReader.readString(); if (Integer.parseInt(file.getName().substring(file.getName().length() - 10, file.getName().length() - 4)) == 1) { // 删除历史文件 FileUtil.clean(newFilePath); } // 备份 FileUtil.move(new File(loFilePath), new File(newFilePath + file.getName()), true); } } } }