简单实现修改内容前后变动日志(注解+反射)
原文链接:https://blog.csdn.net/m0_46144826/article/details/120375142
需求说明
实现目标:把修改的具体字段名以及修改前后内容做日志记录
实现效果:
集装箱数量:【1】变更为【3】;集装箱型:【40 Dry High】变更为【40 Dry Standard】;起运时间:【2021-09-16】变更为【2021-09-30】;自动下单限额:【1200.00】变更为【1500.00】;
1
实现思路
为了做到尽量通用,先假设实体类都实现了序列化 Serializable 。
在实体中添加自定义注解
反射,获取到字段,扫描存在注解的字段
将修改前后的字段值做对比
存在修改则记录日志
代码实现
自定义注解:
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BusLogField {
/**
* 字段名
*/
String name() default "";
/**
* 时间类型下的格式
*/
String pattern() default "";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
实体类添加注解:
@Data
public class MaerskTask implements Serializable {
@BusLogField(name = "集装箱数量")
private Integer containerNum;
@BusLogField(name = "集装箱型")
private String containerShape;
@BusLogField(name = "起运时间", pattern = "yyyy-MM-dd")
private Date originDate;
@BusLogField(name = "接收短信通知号码")
private String noticePhone;
@BusLogField(name = "自动下单限额")
private BigDecimal maxMoney;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
对字段做了删减,测试类型包括:String、Integer、BigDecimal、Date
最后工具类:
/**
* @author shiva 2021/9/18 20:44
*/
public class BusLogUtil {
/**
* 1. 原实体和新实体,反射获得字段
* 2. 遍历获得存在注解的字段
* 3. 对比是否存在修改
* 4. 获得注解内容,拼接
*/
public static String compareEntity(Serializable newEntity, Serializable oldEntity, Class<?> entityClazz) throws IllegalAccessException {
// 新实体的,存在注解的字段
List<Field> fields = getAnnoFileds(entityClazz.getDeclaredFields(), BusLogField.class);
// 准备拼接
StringBuilder sb = new StringBuilder();
for (Field field : fields) {
// 修改访问权限
field.setAccessible(true);
BusLogField annotation = field.getAnnotation(BusLogField.class);
// 获得新旧值,进行对比
Object newValue = field.get(newEntity);
Object oldValue = field.get(oldEntity);
if (newValue.equals(oldValue)) {
continue;
}
//类型判断,对需要做特定转换的类型进行处理
String simpleName = field.getType().getSimpleName();
if ("Date".equals(simpleName)){
//从注解中获得时间格式
SimpleDateFormat sdf = new SimpleDateFormat(annotation.pattern());
newValue = sdf.format(newValue);
oldValue = sdf.format(oldValue);
}
sb.append(annotation.name()).append(":【").append(oldValue).append("】变更为【").append(newValue).append("】;");
}
return sb.toString();
}
public static <T extends Annotation> List<Field> getAnnoFileds(Field[] fields, Class<T> clazz) {
List<Field> result = new ArrayList<>();
// 判空
if (fields.length == 0 || clazz == null) {
return result;
}
// 从所有字段中,筛选出存在日志特定注解的字段
Arrays.stream(fields).forEach(item -> {
if (item.getAnnotation(clazz) != null) {
result.add(item);
}
});
return result;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
调用:
String log = BusLogUtil.compareEntity(newEntity, oldEntity, newEntity.getClass());
System.out.println(log);
1
2
其他说明
因为这只是第一版,花了没多少时间,做得比较简单。
对类型的判断只做了 Date ,可以自行扩展。