需求说明
-
实现目标:把修改的具体字段名以及修改前后内容做日志记录
-
实现效果:
集装箱数量:【1】变更为【3】;集装箱型:【40 Dry High】变更为【40 Dry Standard】;起运时间:【2021-09-16】变更为【2021-09-30】;自动下单限额:【1200.00】变更为【1500.00】;
实现思路
为了做到尽量通用,先假设实体类都实现了序列化 Serializable
。
- 在实体中添加自定义注解
- 反射,获取到字段,扫描存在注解的字段
- 将修改前后的字段值做对比
- 存在修改则记录日志
代码实现
自定义注解:
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface BusLogField {
/**
* 字段名
*/
String name() default "";
/**
* 时间类型下的格式
*/
String pattern() default "";
}
实体类添加注解:
@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;
}
对字段做了删减,测试类型包括: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;
}
}
调用:
String log = BusLogUtil.compareEntity(newEntity, oldEntity, newEntity.getClass());
System.out.println(log);
其他说明
因为这只是第一版,花了没多少时间,做得比较简单。
对类型的判断只做了 Date
,可以自行扩展。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/10274.html