系统操作日志之数据修改变化记录
- 前言
- 效果图
- 如何实现
- 总结
相信大家在自己的系统中都有记录日志吧,像登录日志、操作日志等等
但是一般来说,大家都是获取操作了什么东西,包括它的参数,模块等等,但是你有关心过他的数据变化吗?
前言
如果你想优雅的设计操作日志模块,请参考 美团设计的操作日志模块
真的,阅读后感觉,优雅、实在是优雅至极。
效果图
如何实现
毋庸置疑,肯定需要两次查询,不然你怎么得到前后的数据呢?
你可以在修改前进行查询一次数据,然后再修改后查询数据,当然你是用切面的话当我没说!
这里给大家看下如何比对两次数据的变化,可以通过map来实现,上代码!
@Async
public String getPayInfoMapDiff(Map<String, ?> oldMap, Map<String, ?> newMap) {
// 返回结果
StringBuilder result = new StringBuilder();
// 可以先判断key的总数是否相同,判断是删除了,还是新增了
if (oldMap.size() > newMap.size()) {
// 删除,找到少了哪些
Set<String> diffKey = oldMap.keySet().stream().filter(s -> !newMap.containsKey(s)).collect(Collectors.toSet());
} else {
// 新增,增加了哪些
Set<String> diffKey = newMap.keySet().stream().filter(s -> !oldMap.containsKey(s)).collect(Collectors.toSet());
for (String key : diffKey) {
Map<String, Object> value = JSON.parseObject(JSON.toJSONString(newMap.get(key)), Map.class);
String context = "";
if (value.get("paymentSingleMinCap") != null) {
context += String.format(I18nUtil.get("insert.info.log"), I18nUtil.get("paymentSingleMinCap"), value.getOrDefault("paymentSingleMinCap", ""));
context += String.format(I18nUtil.get("insert.info.log"), I18nUtil.get("paymentSingleMaxCap"), value.getOrDefault("paymentSingleMaxCap", ""));
context += String.format(I18nUtil.get("insert.info.log"), I18nUtil.get("paymentTotalCap"), value.getOrDefault("paymentTotalCap", ""));
}
context += String.format(I18nUtil.get("insert.info.log"), I18nUtil.get("acitve.status"), value.getOrDefault("active", "").equals(1) ? I18nUtil.get("active") : I18nUtil.get("inactive"));
context += String.format(I18nUtil.get("insert.info.log"), I18nUtil.get("Rate"), value.getOrDefault("paymentRate", "") + "‰");
result.append(I18nUtil.get(value.get("paymentName").toString())).append(" ").append(context);
}
}
for (String key : newMap.keySet()) {
for (String s : oldMap.keySet()) {
String context = "";
if (s.equals(key)) {
Map<String, Object> oldValue = JSON.parseObject(JSON.toJSONString(oldMap.get(key)), Map.class);
Map<String, Object> newValue = JSON.parseObject(JSON.toJSONString(newMap.get(key)), Map.class);
if (!oldValue.getOrDefault("paymentSingleMinCap", "").equals(newValue.getOrDefault("paymentSingleMinCap", ""))) {
context += String.format(I18nUtil.get("update.info.log"), I18nUtil.get("paymentSingleMinCap"), oldValue.getOrDefault("paymentSingleMinCap", ""), newValue.getOrDefault("paymentSingleMinCap", ""));
}
if (!oldValue.getOrDefault("paymentSingleMaxCap", "").equals(newValue.getOrDefault("paymentSingleMaxCap", ""))) {
context += String.format(I18nUtil.get("update.info.log"), I18nUtil.get("paymentSingleMaxCap"), oldValue.getOrDefault("paymentSingleMaxCap", ""), newValue.getOrDefault("paymentSingleMaxCap", ""));
}
if (!oldValue.getOrDefault("paymentTotalCap", "").equals(newValue.getOrDefault("paymentTotalCap", ""))) {
context += String.format(I18nUtil.get("update.info.log"), I18nUtil.get("paymentTotalCap"), oldValue.getOrDefault("paymentTotalCap", ""), newValue.getOrDefault("paymentTotalCap", ""));
}
if (!oldValue.get("active").equals(newValue.get("active"))) {
context += String.format(I18nUtil.get("update.info.log"), I18nUtil.get("acitve.status"), oldValue.getOrDefault("active", "").equals(1) ? I18nUtil.get("active") : I18nUtil.get("inactive"), newValue.getOrDefault("active", "").equals(1) ? I18nUtil.get("active") : I18nUtil.get("inactive"));
}
if (!oldValue.get("paymentRate").equals(newValue.get("paymentRate"))) {
context += String.format(I18nUtil.get("update.info.log"), I18nUtil.get("Rate"), oldValue.getOrDefault("paymentRate", "") + "‰", newValue.getOrDefault("paymentRate", "") + "‰");
}
if (!"".equals(context)) {
result.append(I18nUtil.get(newValue.get("paymentName").toString())).append(" ").append(context);
}
}
}
}
return "".equals(result.toString()) ? "无修改" : result.toString();
}
@Async
public String getBaseInfoDiff(Map<String, Object> oldMap, Map<String, Object> newMap) {
StringBuilder result = new StringBuilder();
for (String key : newMap.keySet()) {
StringBuilder context = new StringBuilder();
if (key.contains("updateTime")) {
continue;
}
if (key.contains("accountInfo")) {
// 如果它是空的
Map<String, Object> oldValue = new HashMap<>();
if (!StringUtils.isBlank(oldMap.get(key).toString())){
oldValue = JSON.parseObject(oldMap.get(key).toString(), Map.class);
}
Map<String, Object> newValue = JSON.parseObject(newMap.get(key).toString(), Map.class);
for (String innerKey : newValue.keySet()) {
StringBuilder msg = new StringBuilder();
// 说明是新增的
if (!oldValue.containsKey(innerKey)){
msg.append(String.format(I18nUtil.get("update.info.log"), I18nUtil.get(innerKey), I18nUtil.get(oldValue.getOrDefault(innerKey, "").toString()), I18nUtil.get(newValue.getOrDefault(innerKey, "").toString())));
}
for (String s : oldValue.keySet()) {
if (s.equals(innerKey) && !oldValue.getOrDefault(innerKey, "").toString().equals(newValue.getOrDefault(innerKey, "").toString())) {
msg.append(String.format(I18nUtil.get("update.info.log"), I18nUtil.get(innerKey), I18nUtil.get(oldValue.getOrDefault(innerKey, "").toString()), I18nUtil.get(newValue.getOrDefault(innerKey, "").toString())));
}
}
context.append(msg);
}
} else if ("companyInfo".equals(key)) {
Map<String, Object> oldValue = JSON.parseObject(JSON.toJSONString(oldMap.get("companyInfo")), Map.class);
Map<String, Object> newValue = JSON.parseObject(JSON.toJSONString(newMap.get("companyInfo")), Map.class);
for (String innerKey : newValue.keySet()) {
StringBuilder mes = new StringBuilder();
for (String s : oldValue.keySet()) {
if (s.equals(innerKey) && !oldValue.getOrDefault(innerKey, "").toString().equals(newValue.getOrDefault(innerKey, "").toString())) {
mes.append(String.format(I18nUtil.get("update.info.log"), I18nUtil.get(innerKey), I18nUtil.get(oldValue.getOrDefault(innerKey, "").toString()), I18nUtil.get(newValue.getOrDefault(innerKey, "").toString())));
}
}
context.append(mes);
}
} else {
for (String s : oldMap.keySet()) {
if (s.equals(key) && !newMap.getOrDefault(key, "").toString().equals(oldMap.getOrDefault(key, "").toString())) {
context.append(String.format(I18nUtil.get("update.info.log"), I18nUtil.get(key), I18nUtil.get(oldMap.getOrDefault(key, "").toString()), I18nUtil.get(newMap.getOrDefault(key, "").toString())));
}
}
}
if (!"".equals(context.toString())) {
result.append(context);
}
}
return "".equals(result.toString()) ? "无修改" : result.toString();
}
这个里面有许多东西可以改动,比如说i18n啊,以及对象中有JSON该如何转换,这些都是可以修改的,根据你的业务需要去进行修改即可,这里只是做一个基础版作为参考。
总结
这是最笨的方法,大家有更好的方法也可以评论告诉大家哦,谢谢!
其实把前后两个对象转为map或者json都是可以的,大家都可以试试
公司这个记录操作日志功能是没有用到切面的。