package com.engine.salary.elog.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.engine.salary.elog.entity.dto.LoggerContext; import com.engine.salary.elog.entity.dto.LoggerDetailContext; import com.engine.salary.elog.enums.ElogConsts; import com.engine.salary.elog.service.ILocalElogService; import com.engine.salary.elog.util.ElogUtils; import com.engine.salary.mapper.elog.LocalElogAopDaoMapper; import com.engine.salary.elog.util.db.IdGenerator; import com.engine.salary.elog.util.db.MapperProxyFactory; import com.google.common.collect.Lists; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.CollectionUtils; import weaver.conn.RecordSet; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; /** * @ClassName: LocalElogService * @Description 日志本地持久化 * @Author tanghj * @Date 2021/2/24 11:03 */ public class LocalElogService implements ILocalElogService { private static final Logger logger = LoggerFactory.getLogger(LocalElogService.class); private LocalElogAopDaoMapper getLocalElogAopDaoMapper() { return MapperProxyFactory.getProxy(LocalElogAopDaoMapper.class); } // private RestHighLevelClient client; // // private LazyRollBack lazyRollBack; //数据库类型 private static final String databaseId = new RecordSet().getDBType(); /** * @param context * @param * @return */ @Override public int insertLocalElog(LoggerContext context) { // logger.error("接收到的数据,context:{}",JSONObject.toJSONString(context)); // logger.info("接收到数据的时间:log_date:{}",context.getDate()); if (StringUtils.isEmpty(context.getUuid())) { context.setUuid(UUID.randomUUID().toString().replace("-", "")); } String cusColumns = ""; String cusValus = ""; if (context.getCustomInfo() != null) { JSONObject custom = JSONObject.parseObject(JSON.toJSONString(context.getCustomInfo())); List clobFieldList = context.getClobFieldList(); for (String key : (Set) custom.keySet()) { cusColumns = cusColumns + ", " + key; String keystr = custom.getString(key); //如果keystr包含单引号,将单引号去掉 if (StringUtils.isNotEmpty(keystr) && keystr.contains("'")) { keystr = keystr.replace("'", "''"); } //如果是Oracle数据库 if (ElogConsts.ORACLE.equals(databaseId)) { //clob字段集合不为空且包含此字段 if (!CollectionUtils.isEmpty(clobFieldList) && clobFieldList.contains(key)) { String clobColumnStr = ElogUtils.handleClobColumn(keystr); cusValus = cusValus + ",TO_CLOB( " + clobColumnStr + " )"; } else if (checkStrIsDate(keystr)) { //并且字符串为时间类型格式 则进行特殊处理 cusValus = cusValus + ",TO_DATE('" + keystr + "', 'SYYYY-MM-DD HH24:MI:SS')"; } else { cusValus = cusValus + ",'" + keystr + "'"; } } else { cusValus = cusValus + ",'" + keystr + "'"; } } } normalizationContext(context); String tableName = context.getModuleName() + "_" + context.getFunctionName() + "logs"; //context.setId(IdGenerator.generate()); Integer id = getLocalElogAopDaoMapper().queryElogContextById(context.getId(), tableName); if (id != null) { return 1; } // logger.info("插入前的数据:context:{}",JSONObject.toJSONString(context)); int count = getLocalElogAopDaoMapper().insertElogContext(context, cusColumns, cusValus, tableName); if (context.getDetailContexts() != null) { String detailTableName = context.getModuleName() + "_" + context.getFunctionName() + "logs_detail"; insertBatchDetailPrepared(detailTableName, context); } return count; } /** * 预编译 * * @param detailTableName * @param context */ private void insertBatchDetailPrepared(String detailTableName, LoggerContext context) { // 用mapper //分两种 有无自定义字段 List detailContexts = context.getDetailContexts(); Boolean hasCustonInfo = false; String cusColumns = ""; if (Objects.nonNull(detailContexts.get(0).getCustomDetailInfo())) { hasCustonInfo = true; //有自定义明细字段 JSONObject custom = JSONObject.parseObject(JSON.toJSONString(detailContexts.get(0).getCustomDetailInfo())); for (String key : (Set) custom.keySet()) { cusColumns = cusColumns + ", " + key; } } for (LoggerDetailContext detailContext : detailContexts) { if (StringUtils.isNotEmpty(detailContext.getNewValue())) { String str = detailContext.getNewValue().replaceAll("[\\x{1F600}-\\x{1F64F}\\x{1F300}-\\x{1F5FF}]", ""); detailContext.setNewValue(str); } if (StringUtils.isNotEmpty(detailContext.getOldValue())) { String str = detailContext.getOldValue().replaceAll("[\\x{1F600}-\\x{1F64F}\\x{1F300}-\\x{1F5FF}]", ""); detailContext.setOldValue(str); } if (StringUtils.isNotEmpty(detailContext.getNewRealValue())) { String str = detailContext.getNewRealValue().replaceAll("[\\x{1F600}-\\x{1F64F}\\x{1F300}-\\x{1F5FF}]", ""); detailContext.setNewRealValue(str); } if (StringUtils.isNotEmpty(detailContext.getOldRealValue())) { String str = detailContext.getOldRealValue().replaceAll("[\\x{1F600}-\\x{1F64F}\\x{1F300}-\\x{1F5FF}]", ""); detailContext.setOldRealValue(str); } detailContext.setTenant_key(context.getTenant_key()); detailContext.setCreate_time(new Date()); detailContext.setUpdate_time(new Date()); detailContext.setCreator(context.getLogOperator()); detailContext.setId(IdGenerator.generate()); if (hasCustonInfo) { String cusValus = ""; //如果有明细 JSONObject custom = JSONObject.parseObject(JSON.toJSONString(detailContext.getCustomDetailInfo())); for (String key : (Set) custom.keySet()) { String keystr = custom.getString(key); //如果keystr包含单引号,将单引号去掉 if (StringUtils.isNotEmpty(keystr) && keystr.contains("'")) { keystr = keystr.replace("'", "''"); } cusValus = cusValus + ",'" + keystr + "'"; } detailContext.setCusValus(cusValus); } } if (hasCustonInfo) { List> partition = Lists.partition(detailContexts, 50); for (int i = 0; i < partition.size(); i++) { getLocalElogAopDaoMapper().insertElogDetailPreparedHasCustonInfo(detailTableName, partition.get(i), context.getUuid(), cusColumns); } } else { List> partition = Lists.partition(detailContexts, 50); partition.forEach(part -> { getLocalElogAopDaoMapper().insertElogDetailPrepared(detailTableName, part, context.getUuid()); }); } } private void normalizationContext(LoggerContext context) { String params = ""; if (StringUtils.isNotEmpty(context.getParamsStr())) { params = context.getParamsStr(); } else if (context.getParams() != null) { params = ElogUtils.compress(JSONObject.toJSONString(context.getParams())); } context.setParamsStr(params); if (StringUtils.isBlank(context.getCancelContextStr())) { context.setCancelContextStr(context.getCancelContext() == null ? "" : JSONObject.toJSONString(context.getCancelContext())); } if (StringUtils.isBlank(context.getRedoContextStr())) { context.setRedoContextStr(context.getRedoContext() == null ? "" : JSONObject.toJSONString(context.getRedoContext())); } if (StringUtils.isEmpty(context.getOperatedesc())) { context.setOperatedesc(""); } else { //todo 兼容emojo特殊字符 没有时间 先暴力替换 String str = context.getOperatedesc().replaceAll("[\\x{1F600}-\\x{1F64F}\\x{1F300}-\\x{1F5FF}]", ""); context.setOperatedesc(str); } if (Objects.isNull(context.getDate())) { context.setDate(new Date()); } if (StringUtils.isEmpty(context.getOperator())) { context.setLogOperator(-1l); } else { context.setLogOperator(Long.parseLong(context.getOperator())); } if (StringUtils.isEmpty(context.getTargetId())) { context.setLogTargetid(-1l); } else { context.setLogTargetid(Long.parseLong(context.getTargetId())); } if (StringUtils.isEmpty(context.getClientIp())) { context.setClientIp("127.0.0.1"); } if (Objects.isNull(context.getCreate_time())) { context.setCreate_time(new Date()); } if (Objects.isNull(context.getUpdate_time())) { context.setUpdate_time(new Date()); } if (Objects.isNull(context.getDelete_type())) { context.setDelete_type(0); } } private void insertBatchDetailSql(String detailTableName, LoggerContext context) { String standardField = "id, mainid, uuid, tablename, fieldname, newvalue, oldvalue, fielddesc, showorder, dataid, belongDataid, isDetail, tenant_key,creator, newRealValue, oldRealValue,tableNameDesc, tableNameLabelId,fieldNameLabelId, create_time, update_time"; Boolean hasCustonInfo = false; StringBuilder sb = new StringBuilder(); sb.append("INSERT INTO ").append(detailTableName).append("(").append(standardField); //List collect = detailContexts.stream().filter(s -> Objects.nonNull(s.getCustomDetailInfo())).collect(Collectors.toList()); List detailContexts = context.getDetailContexts(); if (Objects.nonNull(detailContexts.get(0).getCustomDetailInfo())) { hasCustonInfo = true; //有自定义明细字段 String cusColumns = ""; JSONObject custom = JSONObject.parseObject(JSON.toJSONString(detailContexts.get(0).getCustomDetailInfo())); for (String key : (Set) custom.keySet()) { cusColumns = cusColumns + ", " + key; } sb.append(cusColumns); } sb.append(")"); if ("oracle".equalsIgnoreCase(databaseId)) { sb.append(" ").append(String.join(" UNION ALL ", getBatchInsertValue(context, hasCustonInfo, true))); } else { sb.append(" VALUES ").append(String.join(",", getBatchInsertValue(context, hasCustonInfo, false))); } try { getLocalElogAopDaoMapper().batchInsertDetail(sb.toString()); } catch (Exception e) { logger.error("明细批量添加sql是:{},批量插入明细失败,{}", sb.toString(), e.getMessage(), e); } } private List getBatchInsertValue(LoggerContext context, boolean hasCustomInfo, boolean isOracle) { LocalDateTime localDateTime = LocalDateTime.now(); String nowDate = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); List detailContexts = context.getDetailContexts(); List batchValue = new ArrayList<>(); for (LoggerDetailContext detailContext : detailContexts) { detailContext.setTenant_key(context.getTenant_key()); detailContext.setCreator(context.getLogOperator()); detailContext.setId(IdGenerator.generate()); StringBuilder sb = new StringBuilder(); sb.append(isOracle ? " SELECT " : " ( "); sb.append(detailContext.getId()) .append(",'").append(context.getUuid()).append("'") .append(",'").append(detailContext.getUuid()).append("'") .append(",'").append(detailContext.getTableName()).append("'") .append(",'").append(detailContext.getFieldName()).append("'") .append(",'").append(transferString(detailContext.getNewValue())).append("'") .append(",'").append(transferString(detailContext.getOldValue())).append("'") .append(",'").append(detailContext.getFieldDesc()).append("'") .append(",'").append(detailContext.getShoworder()).append("'") .append(",'").append(detailContext.getDataid()).append("'") .append(",'").append(detailContext.getBelongDataid()).append("'") .append(",'").append(detailContext.getIsDetail()).append("'") .append(",'").append(detailContext.getTenant_key()).append("'") .append(",'").append(detailContext.getCreator()).append("'") .append(",'").append(transferString(detailContext.getNewRealValue())).append("'") .append(",'").append(transferString(detailContext.getOldRealValue())).append("'") .append(",'").append(detailContext.getTableNameDesc()).append("'") .append(",'").append(detailContext.getTableNameLabelId()).append("'") .append(",'").append(detailContext.getFieldNameLabelId()).append("'") .append(",").append(handleValue(nowDate, databaseId)) .append(",").append(handleValue(nowDate, databaseId)); if (hasCustomInfo) { String cusValus = ""; //如果有明细 JSONObject custom = JSONObject.parseObject(JSON.toJSONString(detailContext.getCustomDetailInfo())); for (String key : (Set) custom.keySet()) { String keystr = custom.getString(key); //如果keystr包含单引号,将单引号去掉 if (StringUtils.isNotEmpty(keystr) && keystr.contains("'")) { keystr = keystr.replace("'", "''"); } cusValus = cusValus + ",'" + keystr + "'"; } sb.append(cusValus); } String sql = isOracle ? sb.append(" from dual ").toString() : sb.append(")").toString(); batchValue.add(sql); } return batchValue; } private String transferString(String str) { if (StringUtils.isNotEmpty(str)) { str = str.replaceAll("#\\{", "\\\\\\\\#{"); if (str.contains("'")) { str = str.replace("'", "''"); } } return str; } private String handleValue(String nowDate, String databaseId) { switch (databaseId) { case "mysql": return "'" + nowDate + "'"; case "oracle": return "TO_DATE('" + nowDate + "','YYYY-MM-DD HH24:MI:SS')"; case "sqlserver": return "'" + nowDate + "'"; case "postgresql": return "'" + nowDate + "'"; } return nowDate; } // private void insertESElogCenter(LoggerContext context, String customInfo, String tableName) { // //将数据转换为ES的数据格式 // LogESDoc logESDoc = LogESDoc.context2Doc(context, customInfo, tableName); // String json = JSON.toJSONString(logESDoc); // String elogESTableName = ElogEsUtils.getElogESTableName(true, ElogEsUtils.getDateStr(context.getDate())); // IndexRequest indexRequest = new IndexRequest(elogESTableName).id(logESDoc.getId().toString()); // indexRequest.source(json, XContentType.JSON); // // try { // client.index(indexRequest, RequestOptions.DEFAULT); // } catch (IOException e) { //// logger.info("主表数据添加失败:{}",e.getMessage()); // } // } @Override public int insertElogDetail(LoggerDetailContext loggerDetailContext, String mainId, String detailTableName) { String cusColumns = ""; String cusValus = ""; if (loggerDetailContext.getCustomDetailInfo() != null) { JSONObject custom = JSONObject.parseObject(JSON.toJSONString(loggerDetailContext.getCustomDetailInfo())); for (String key : (Set) custom.keySet()) { cusColumns = cusColumns + ", " + key; String keystr = custom.getString(key); //如果keystr包含单引号,将单引号去掉 if (StringUtils.isNotEmpty(keystr) && keystr.contains("'")) { keystr = keystr.replace("'", "''"); } cusValus = cusValus + ",'" + keystr + "'"; } } loggerDetailContext.setId(IdGenerator.generate()); return getLocalElogAopDaoMapper().insertElogDetail(loggerDetailContext, mainId, cusColumns, cusValus, detailTableName); } // @Override // public void rollBackElog(LoggerContext context) { // //根据ID 判断数据是否存在 // // String tableName = getElogTableName(context.getModuleName(), context.getFunctionName()); // Integer id = getLocalElogAopDaoMapper().queryElogContextById(context.getId(), tableName); // //没查到就直接返回 // if (id == null) { // lazyRollBack.delayedRollBack(context); // return; // } // getLocalElogAopDaoMapper().rollBackElogById(context.getId(), tableName); // //// if (context.getDetailContexts() != null) { // String detailTableName = context.getModuleName() + "_" + context.getFunctionName() + "logs_detail"; // //根据uuid回滚 // getLocalElogAopDaoMapper().rollBackDetailElogByUUID(context.getUuid(), detailTableName); //// } // // // } /** * 判断字符串是否为日期格式 */ public static Boolean checkStrIsDate(String str) { if (StringUtils.isBlank(str)) { return false; } else { try { LocalDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); return true; } catch (Exception e) { return false; } } } private String getElogTableName(String moduleName, String functionName) { // List list = Arrays.asList("meetingTopic", "meetingService", "meetingDecision", "meetingSign", "meetingSignSet", "meetingMember", "meetingShare"); // if (list.contains(moduleName)) { // return "meeting"+ "_" + functionName + "logs"; // } return moduleName + "_" + functionName + "logs"; } }