You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

443 lines
19 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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.elog.util.db.IdGenerator;
import com.engine.salary.elog.util.db.MapperProxyFactory;
import com.engine.salary.mapper.elog.LocalElogAopDaoMapper;
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 <T>
* @return
*/
@Override
public <T> int insertLocalElog(LoggerContext<T> 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<String> clobFieldList = context.getClobFieldList();
for (String key : (Set<String>) 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<LoggerDetailContext> 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<String>) 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<String>) 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<List<LoggerDetailContext>> partition = Lists.partition(detailContexts, 50);
for (int i = 0; i < partition.size(); i++) {
getLocalElogAopDaoMapper().insertElogDetailPreparedHasCustonInfo(detailTableName, partition.get(i), context.getUuid(), cusColumns);
}
} else {
List<List<LoggerDetailContext>> partition = Lists.partition(detailContexts, 50);
partition.forEach(part -> {
getLocalElogAopDaoMapper().insertElogDetailPrepared(detailTableName, part, context.getUuid());
});
}
}
private <T> void normalizationContext(LoggerContext<T> 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<LoggerDetailContext> collect = detailContexts.stream().filter(s -> Objects.nonNull(s.getCustomDetailInfo())).collect(Collectors.toList());
List<LoggerDetailContext> 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<String>) 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<String> getBatchInsertValue(LoggerContext context, boolean hasCustomInfo, boolean isOracle) {
LocalDateTime localDateTime = LocalDateTime.now();
String nowDate = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
List<LoggerDetailContext> detailContexts = context.getDetailContexts();
List<String> 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<String>) 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 <T> void insertESElogCenter(LoggerContext<T> 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 <T> int insertElogDetail(LoggerDetailContext<T> 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<String>) 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 <T> void rollBackElog(LoggerContext<T> 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<String> list = Arrays.asList("meetingTopic", "meetingService", "meetingDecision", "meetingSign", "meetingSignSet", "meetingMember", "meetingShare");
// if (list.contains(moduleName)) {
// return "meeting"+ "_" + functionName + "logs";
// }
return moduleName + "_" + functionName + "logs";
}
}