系统操作日志之数据修改变化记录
- 前言
- 效果图
- 如何实现
- 总结
相信大家在自己的系统中都有记录日志吧,像登录日志、操作日志等等
但是一般来说,大家都是获取操作了什么东西,包括它的参数,模块等等,但是你有关心过他的数据变化吗?
前言
如果你想优雅的设计操作日志模块,请参考 美团设计的操作日志模块
真的,阅读后感觉,优雅、实在是优雅至极。
效果图
如何实现
毋庸置疑,肯定需要两次查询,不然你怎么得到前后的数据呢?
你可以在修改前进行查询一次数据,然后再修改后查询数据,当然你是用切面的话当我没说!
这里给大家看下如何比对两次数据的变化,可以通过map来实现,上代码!
@Asyncpublic 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();}@Asyncpublic 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都是可以的,大家都可以试试
公司这个记录操作日志功能是没有用到切面的。