512 lines
23 KiB
Java
Raw Normal View History

2023-02-16 15:28:15 +08:00
package com.zhgd.xmgl.config;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
2023-02-16 15:28:15 +08:00
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
2023-02-16 15:28:15 +08:00
import com.zhgd.annotation.OperLog;
import com.zhgd.jeecg.common.util.SpringContextUtils;
import com.zhgd.xmgl.constant.Cts;
import com.zhgd.xmgl.entity.dto.OperLogDataChange;
import com.zhgd.xmgl.entity.dto.OperLogDataChangeField;
import com.zhgd.xmgl.entity.dto.OperLogInsertChange;
2023-02-16 15:28:15 +08:00
import com.zhgd.xmgl.modules.basicdata.entity.OperationLog;
import com.zhgd.xmgl.modules.basicdata.service.IOperationLogService;
2024-06-28 20:51:36 +08:00
import com.zhgd.xmgl.security.util.SecurityUtils;
2023-02-16 15:28:15 +08:00
import com.zhgd.xmgl.util.IpUtil;
import com.zhgd.xmgl.util.ThreadLocalUtil;
import io.swagger.annotations.ApiModelProperty;
2024-04-14 21:05:01 +08:00
import lombok.extern.slf4j.Slf4j;
2024-06-28 20:51:36 +08:00
import org.apache.commons.lang3.ArrayUtils;
2023-02-16 15:28:15 +08:00
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
2023-02-16 15:28:15 +08:00
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
2024-07-09 11:07:16 +08:00
import org.springframework.web.multipart.MultipartFile;
2023-02-16 15:28:15 +08:00
import javax.servlet.http.HttpServletRequest;
2024-06-28 20:51:36 +08:00
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.lang.reflect.Field;
2023-02-16 15:28:15 +08:00
import java.lang.reflect.Method;
2024-06-28 20:51:36 +08:00
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
2024-06-28 20:51:36 +08:00
import java.util.stream.Collectors;
import java.util.stream.Stream;
2023-02-16 15:28:15 +08:00
/**
* @program: wisdomSite
* @description: 切面处理类操作日志记录处理
* @author: Mr.Peng
* @create: 2021-05-06 18:04
**/
@Aspect
@Component
2024-04-14 21:05:01 +08:00
@Slf4j
2023-02-16 15:28:15 +08:00
public class OperLogAspect {
Pattern logNamePattern = Pattern.compile("(.+)(\\d+:.+;)+");
Pattern logNamePattern1 = Pattern.compile("(\\d+)(\\D+)");
2023-02-16 15:28:15 +08:00
@Autowired
private IOperationLogService operationLogService;
/**
* 设置操作日志切入点 记录操作日志 在注解的位置切入代码
2024-06-28 20:51:36 +08:00
*/
2023-02-16 15:28:15 +08:00
@Pointcut("@annotation(com.zhgd.annotation.OperLog)")
2024-06-28 20:51:36 +08:00
public void operLogPoinCut() {
2023-02-16 15:28:15 +08:00
}
/**
2024-06-28 20:51:36 +08:00
* 设置操作异常切入点记录异常日志 扫描所有controller包下操作
*/
2023-02-16 15:28:15 +08:00
@Pointcut("execution(* com.*.*.*.*.controller..*.*(..))")
2024-06-28 20:51:36 +08:00
public void operExceptionLogPoinCut() {
2023-02-16 15:28:15 +08:00
}
/**
2024-06-28 20:51:36 +08:00
* 正常返回通知拦截用户操作日志连接点正常执行完成后执行 如果连接点抛出异常则不会执行
*
* @param joinPoint 切入点
* @param keys 返回结果
*/
2023-02-16 15:28:15 +08:00
@AfterReturning(value = "operLogPoinCut()", returning = "keys")
public void saveOperLog(JoinPoint joinPoint, Object keys) {
2024-06-28 20:51:36 +08:00
// 获取RequestAttributes
2023-02-16 15:28:15 +08:00
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 从获取RequestAttributes中获取HttpServletRequest的信息
2024-07-09 11:07:16 +08:00
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
2023-02-16 15:28:15 +08:00
OperationLog operlog = new OperationLog();
try {
2024-07-09 11:07:16 +08:00
// 主键ID
//operlog.setOperId(IdGenerator.getUUID());
2023-02-16 15:28:15 +08:00
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
Method method = signature.getMethod();
// 获取操作
OperLog opLog = method.getAnnotation(OperLog.class);
if (opLog != null) {
String operModul = opLog.operModul();
String operType = opLog.operType();
String operDesc = opLog.operDesc();
2024-07-09 11:07:16 +08:00
// 操作模块
operlog.setOperModul(operModul);
// 操作类型
operlog.setOperType(operType);
// 操作描述
operlog.setOperDesc(operDesc);
2023-02-16 15:28:15 +08:00
}
// 获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
// 获取请求的方法名
String methodName = method.getName();
methodName = className + "." + methodName;
operlog.setOperMethod(methodName);
// 请求的参数
Map<String, String> rtnMap = converMap(request.getParameterMap());
// 将参数所在的数组转换成json
String params = JSON.toJSONString(rtnMap);
2024-07-09 11:07:16 +08:00
// 请求参数
operlog.setOperRequParam(params);
2024-06-28 20:51:36 +08:00
Object[] args = joinPoint.getArgs();
if (ArrayUtils.isNotEmpty(args)) {
2024-07-09 11:07:16 +08:00
List<Object> logArgs = Arrays.stream(args).filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse) && !(arg instanceof MultipartFile))).collect(Collectors.toList());
2024-06-28 20:51:36 +08:00
operlog.setBody(JSON.toJSONString(logArgs));
} else {
log.info("Request Args : null");
}
2023-02-16 15:28:15 +08:00
// 请求用户ID
String operUserId = request.getHeader("operateId");
2024-06-28 20:51:36 +08:00
operlog.setOperUserId(operUserId);
if (StringUtils.isBlank(operUserId) && SecurityUtils.getUser() != null) {
operlog.setOperUserId(String.valueOf(SecurityUtils.getUser().getUserId()));
2023-02-16 15:28:15 +08:00
}
//operlog.setOperUserName(); // 请求用户名称
2024-07-09 11:07:16 +08:00
// 请求IP
operlog.setOperIp(IpUtil.getRemortIP(request));
// 请求URI
operlog.setOperUri(request.getRequestURI());
// 请求方法
operlog.setOperMethod(request.getMethod());
// 创建时间
operlog.setOperCreateTime(new Date());
2024-06-28 20:51:36 +08:00
if ("com.zhgd.xmgl.modules.basicdata.controller.LoginController.login".equals(operlog.getOperMethod())) {
2023-02-16 15:28:15 +08:00
if (keys != null) {
2024-06-28 20:51:36 +08:00
JSONObject json = JSONUtil.parseObj(keys);
if ("200".equals(json.getStr("code"))) {
JSONObject jsonObject = json.getJSONObject("result");
String userId = jsonObject.getStr("userId");
2024-07-19 10:31:31 +08:00
operlog.setOperUserId(userId);
2023-02-16 15:28:15 +08:00
}
}
}
try {
//前后数据变化
List<OperLogDataChange> beforeList = ThreadLocalUtil.getByKey(Cts.TL_UPDATE_DEL_BEFORE_PARAM, List.class);
List<OperLogInsertChange> insertList = ThreadLocalUtil.getByKey(Cts.TL_INSERT_BEFORE_PARAM, List.class);
if (beforeList != null || insertList != null) {
if (beforeList == null) {
beforeList = new ArrayList<>();
}
List<OperLogDataChange> afterList = new ArrayList<>();
for (OperLogDataChange jo : beforeList) {
String mapperName = jo.getMapperName();
String whereSql = jo.getWhereSql();
List result = (List) jo.getResult();
if (CollUtil.isEmpty(result)) {
continue;
}
//根据修改之前的数据取出id列表查询之后的数据
Field idField = this.getIdField(result);
List idList = (List) result.stream().map(o -> {
try {
return idField.get(o);
} catch (IllegalAccessException e) {
log.error("", e);
}
return null;
}).collect(Collectors.toList());
QueryWrapper<Object> wrapper = Wrappers.query().in(StrUtil.toUnderlineCase(idField.getName()), idList);
Object mapperObj = SpringContextUtils.getBean(Class.forName(mapperName));
Method selectListMethod = ReflectUtil.getMethod(mapperObj.getClass(), "selectList", QueryWrapper.class);
Object queryResult = ReflectUtil.invoke(mapperObj, selectListMethod, wrapper);
OperLogDataChange operLogDataChange = new OperLogDataChange();
operLogDataChange.setMapperName(mapperName);
operLogDataChange.setWhereSql(whereSql);
operLogDataChange.setResult(queryResult);
operLogDataChange.setTimestamp(System.currentTimeMillis());
afterList.add(operLogDataChange);
}
if (insertList != null) {
//补充完整 insertList根据主键id查询插入后的数据
for (OperLogInsertChange change : insertList) {
String mapperName = change.getMapperName();
List result = (List) change.getResult();
Object mapperObj = SpringContextUtils.getBean(Class.forName(mapperName));
Method selectIdMethod = ReflectUtil.getMethod(mapperObj.getClass(), "selectById", Serializable.class);
Field idField = this.getIdField(result);
Object obj = result.get(0);
BeanUtil.copyProperties(ReflectUtil.invoke(mapperObj, selectIdMethod, idField.get(obj)), obj);
}
}
Pair<String, String> changePair = getBeforeAndAfterDataChange(beforeList, afterList);
operlog.setDataChangeBefore(changePair.getLeft());
operlog.setDataChangeAfter(changePair.getRight());
}
} catch (Exception e) {
log.error("处理前后数据异常", e);
}
2024-07-19 10:31:31 +08:00
operationLogService.save(operlog);
2023-02-16 15:28:15 +08:00
} catch (Exception e) {
2024-04-14 21:05:01 +08:00
log.error("error", e);
2023-02-16 15:28:15 +08:00
}
}
/**
* 获取前后数据变化
*
* @param beforeList
* @param afterList
* @return
*/
private Pair<String, String> getBeforeAndAfterDataChange(List<OperLogDataChange> beforeList, List<OperLogDataChange> afterList) {
Map<String, List<OperLogDataChange>> beforeMapperNameMap = beforeList.stream().collect(Collectors.groupingBy(OperLogDataChange::getMapperName));
Map<String, List<OperLogDataChange>> afterMapperNameMap = afterList.stream().collect(Collectors.groupingBy(OperLogDataChange::getMapperName));
Set<String> mapperNames = new HashSet<>(CollUtil.addAll(new HashSet<>(beforeMapperNameMap.keySet()), new HashSet<>(afterMapperNameMap.keySet())));
List<OperLogInsertChange> insertList = ThreadLocalUtil.getByKey(Cts.TL_INSERT_BEFORE_PARAM, List.class);
Map<String, List<OperLogInsertChange>> insertMapperNameMap = new HashMap<>();
if (CollUtil.isNotEmpty(insertList)) {
List<String> names = insertList.stream().map(OperLogInsertChange::getMapperName).collect(Collectors.toList());
mapperNames = new HashSet<>(CollUtil.addAll(mapperNames, names));
insertMapperNameMap = insertList.stream().collect(Collectors.groupingBy(OperLogInsertChange::getMapperName));
}
List<List<OperLogDataChangeField>> resultBeforeList = new ArrayList<>();
List<List<OperLogDataChangeField>> resultAfterList = new ArrayList<>();
for (String mapperName : mapperNames) {
List<OperLogDataChange> befores = beforeMapperNameMap.get(mapperName);
Field idField;
List beforeDataList = new ArrayList();
if (befores != null) {
//更新或删除时候
idField = getIdField((List) befores.get(0).getResult());
beforeDataList = getBeforeDataList(befores, idField);
} else {
//新增时候
List<OperLogInsertChange> operLogInsertChanges = insertMapperNameMap.get(mapperName);
idField = getIdField((List) operLogInsertChanges.get(0).getResult());
}
List afterDataList = getAfterDataList(idField, afterMapperNameMap.get(mapperName), insertMapperNameMap.get(mapperName));
Map<String, Object> beforeDataIdMap = (Map<String, Object>) beforeDataList.stream().collect(Collectors.toMap(o -> {
try {
return idField.get(o).toString();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return "";
}, Function.identity()));
Map<String, Object> afterDataIdMap = (Map<String, Object>) afterDataList.stream().collect(Collectors.toMap(o -> {
try {
return idField.get(o).toString();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return "";
}, Function.identity()));
//对比集合的数据
Field finalIdField = idField;
List<String> idList = (List) CollUtil.addAll(beforeDataList, afterDataList).stream().map(o -> {
try {
return finalIdField.get(o).toString();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return "";
}).distinct().collect(Collectors.toList());
for (String id : idList) {
Object afterObj = afterDataIdMap.get(id);
Object beforeObj = beforeDataIdMap.get(id);
List<OperLogDataChangeField> resultBeforeOneObjList = new ArrayList<>();
List<OperLogDataChangeField> resultAfterOneObjList = new ArrayList<>();
if (beforeObj != null && afterObj != null) {
//更新时候都不为null
Field[] fields = afterObj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (!field.isAnnotationPresent(ApiModelProperty.class)) {
continue;
}
try {
Object oldValue = field.get(beforeObj);
Object newValue = field.get(afterObj);
if (!Objects.equals(newValue, oldValue) || idField.getName().equals(field.getName())) {
resultBeforeOneObjList.add(getOperLogDataChangeField(field, oldValue));
resultAfterOneObjList.add(getOperLogDataChangeField(field, newValue));
}
} catch (Exception e) {
log.error("更新时候报错", e);
}
}
} else if (beforeObj != null && afterObj == null) {
//删除时候
Field[] fields = beforeObj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (!field.isAnnotationPresent(ApiModelProperty.class)) {
continue;
}
try {
Object oldValue = field.get(beforeObj);
if (oldValue != null) {
resultBeforeOneObjList.add(getOperLogDataChangeField(field, oldValue));
}
} catch (Exception e) {
log.error("删除时候报错", e);
}
}
} else if (beforeObj == null && afterObj != null) {
//新增时候
Field[] fields = afterObj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (!field.isAnnotationPresent(ApiModelProperty.class)) {
continue;
}
try {
Object newValue = field.get(afterObj);
if (newValue != null) {
resultAfterOneObjList.add(getOperLogDataChangeField(field, newValue));
}
} catch (Exception e) {
log.error("新增时候报错", e);
}
}
}
if (CollUtil.isNotEmpty(resultBeforeOneObjList) && resultBeforeOneObjList.size() > 1) {
resultBeforeList.add(resultBeforeOneObjList);
}
if (CollUtil.isNotEmpty(resultAfterOneObjList) && resultAfterOneObjList.size() > 1) {
resultAfterList.add(resultAfterOneObjList);
}
}
}
return new ImmutablePair(StrUtil.join("", resultBeforeList.stream().map(fields -> StrUtil.join("", fields.stream().map(map -> map.getName() + "" + map.getVal()).collect(Collectors.toList()))).collect(Collectors.toList())),
StrUtil.join("", resultAfterList.stream().map(fields -> StrUtil.join("", fields.stream().map(map -> map.getName() + "" + map.getVal()).collect(Collectors.toList()))).collect(Collectors.toList())));
}
/**
* 获取前后变化的字段名和值
*
* @param field
* @param val
* @return
*/
private OperLogDataChangeField getOperLogDataChangeField(Field field, Object val) {
OperLogDataChangeField bm = new OperLogDataChangeField();
String name = field.getAnnotation(ApiModelProperty.class).value();
String v = null;
if (val instanceof Integer) {
Matcher matcher = logNamePattern.matcher(name);
if (matcher.matches()) {
//如类型1:人员;2:人员照片;3:人员权限;4:固定车辆;5:固定车辆群组;6:临时车;7:车辆布防;
for (String s : matcher.group(2).split(";")) {
String[] split = s.split(":");
if (Objects.equals(split[0], val.toString())) {
// v = split[1];
name = name.split("")[0];
break;
}
}
} else {
boolean isMatch = false;
Matcher matcher1 = logNamePattern1.matcher(name);
while (matcher1.find()) {
isMatch = true;
if (matcher1.group(1).equals(val.toString())) {
if (name.contains("")) {
name = StrUtil.subBefore(name, "", false);
} else {
name = field.getName();
}
// v = matcher1.group(2);
break;
}
}
if (!isMatch) {
name = field.getName();
}
}
}
if (v == null) {
v = getVal(val);
}
bm.setName(name);
bm.setVal(v);
return bm;
}
/**
* 获取值
*
* @param val
* @return
*/
private String getVal(Object val) {
if (val instanceof Date) {
return DateUtil.formatDateTime((Date) val);
} else {
return Convert.toStr(val);
}
}
/**
* 获取主键id的属性
*
* @param result
* @return
*/
private Field getIdField(List result) {
Field idField = null;
Object obj = result.get(0);
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.isAnnotationPresent(TableId.class)) {
idField = field;
break;
}
}
return idField;
}
/**
* 获取之后的数据
*
* @param idField
* @param afterList
* @param insertList
* @return
*/
private List getAfterDataList(Field idField, List<OperLogDataChange> afterList, List<OperLogInsertChange> insertList) {
Stream stream1;
if (afterList != null) {
stream1 = afterList.stream().flatMap(map -> ((List) map.getResult()).stream());
} else {
stream1 = Collections.emptyList().stream();
}
if (CollUtil.isNotEmpty(insertList)) {
Stream stream2 = insertList.stream().flatMap(map -> ((List) map.getResult()).stream());
stream1 = Stream.concat(stream1, stream2);
}
List rtList = (List) stream1.collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(
o -> {
try {
return idField.get(o).toString();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return "";
}))), ArrayList::new));
return rtList;
}
/**
* 获取之前的数据
*
* @param list
* @param idField
* @return
*/
private List getBeforeDataList(List<OperLogDataChange> list, Field idField) {
return (List) list.stream().flatMap(map -> ((List) map.getResult()).stream()).collect(Collectors.collectingAndThen(
Collectors.toCollection(() -> new TreeSet<>(
Comparator.comparing(
o -> {
try {
return idField.get(o).toString();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return "";
}))), ArrayList::new));
}
2024-06-28 20:51:36 +08:00
/**
2023-02-16 15:28:15 +08:00
* 转换request 请求参数
*
* @param paramMap request获取的参数数组
*/
2024-06-28 20:51:36 +08:00
public Map<String, String> converMap(Map<String, String[]> paramMap) {
Map<String, String> rtnMap = new HashMap<String, String>();
for (String key : paramMap.keySet()) {
rtnMap.put(key, paramMap.get(key)[0]);
}
return rtnMap;
}
2023-02-16 15:28:15 +08:00
}