1.首先定义一个接口,接口中有两个方法,分别是将属性转换成英文描述和中文描述。
其实就是将数据库中记录的 0 1 ,转换成后面的描述
这边定义了中文转换为默认方法,是因为有些属性不需要进行中文转换,或者该属性的枚举值中没有中文描述,你也可以不定义为默认方法
java
public interface ColumnConverter {
/**
* 英文值
*/
Object enConverter(Object value);
/**
* 中文值
*/
default Object cnConverter(Object value) {
return enConverter(value);
}
}
2.然后我们就可以定义一个类,该类中有很多静态类【不同的静态类用于不同属性的枚举值转换】,代码如下
java
@Slf4j
public class ColumnStrategy {
private final Map<Class<? extends ColumnConverter>, ColumnConverter> converterMap = new HashMap<>();
private ColumnStrategy() {
}
/**
* 获取单例
*/
public static ColumnStrategy getInstance() {
return INSTANCE.Instance;
}
public ColumnConverter getConverter(Class<? extends ColumnConverter> converterClass) {
try {
if (converterMap.containsKey(converterClass)) {
return converterMap.get(converterClass);
}
Constructor<? extends ColumnConverter> constructor = converterClass.getConstructor();
ColumnConverter columnConverter = constructor.newInstance();
converterMap.put(converterClass, columnConverter);
return columnConverter;
} catch (Exception e) {
log.error("构造转换器对象异常", e);
return null;
}
}
public ColumnConverter getDefaultConverter() {
ColumnConverter defaultConverter = converterMap.get(AutoConverter.class);
if (defaultConverter != null) {
return defaultConverter;
}
AutoConverter autoConverter = new AutoConverter();
converterMap.put(AutoConverter.class, autoConverter);
return autoConverter;
}
private static class INSTANCE {
private static final ColumnStrategy Instance = new ColumnStrategy();
}
/**
* 默认转换器
*/
public static class AutoConverter implements ColumnConverter {
@Override
public Object enConverter(Object value) {
return value;
}
}
public static class CarrierLevelType implements ColumnConverter {
@Override
public Object enConverter(Object value) {
return Optional.ofNullable(value)
.map(e -> CarrierTypeEnum.getByCode((int) e))
.map(CarrierTypeEnum::getEnDesc)
.orElse(null);
}
@Override
public Object cnConverter(Object value) {
return Optional.ofNullable(value)
.map(e -> CarrierTypeEnum.getByCode((int) e))
.map(CarrierTypeEnum::getDescription)
.orElse(null);
}
}
/**
* 结果集转换器
* 将<转换为< (前端要求)
*/
public static class OperationDescResultConverter implements ColumnConverter {
@Override
public Object enConverter(Object value) {
return ((String) value).replaceAll(KeyboardSpecialCharConstants.LESS, KeyboardSpecialCharConstants.LESS_ESCAPING);
}
}
public static class BusinessStatusType implements ColumnConverter {
@Override
public Object enConverter(Object value) {
return Optional.ofNullable(value)
.map(e -> BusinessStatusEnum.getByCode((int) e))
.map(BusinessStatusEnum::getValue)
.orElse(null);
}
@Override
public Object cnConverter(Object value) {
return Optional.ofNullable(value)
.map(e -> BusinessStatusEnum.getByCode((int) e))
.map(BusinessStatusEnum::getCnValue)
.orElse(null);
}
}
public static class PriceCheckType implements ColumnConverter {
@Override
public Object enConverter(Object value) {
return Optional.ofNullable(value)
.map(e -> PriceCheckModeEnum.getEnumByCode((int) e))
.map(PriceCheckModeEnum::getModeDescEn)
.orElse(null);
}
@Override
public Object cnConverter(Object value) {
return Optional.ofNullable(value)
.map(e -> PriceCheckModeEnum.getEnumByCode((int) e))
.map(PriceCheckModeEnum::getModeDesc)
.orElse(null);
}
}
public static class RealPriceCalType implements ColumnConverter {
@Override
public Object enConverter(Object value) {
return Optional.ofNullable(value)
.map(e -> RealPriceCalMethodEnum.getEnumByCode((int) e))
.map(RealPriceCalMethodEnum::getMethodDescEn)
.orElse(null);
}
@Override
public Object cnConverter(Object value) {
return Optional.ofNullable(value)
.map(e -> RealPriceCalMethodEnum.getEnumByCode((int) e))
.map(RealPriceCalMethodEnum::getMethodDesc)
.orElse(null);
}
}
}
3.然后我们定义一个注解,该注解用于我们实际进行比较的类中上,具体值是否需要进行枚举值转换,以及字段的中英文名称
java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ColumnInfo {
/**
* 字段中文名
*/
String cnName() default "";
/**
* 字段英文名
*/
String enName() default "";
/**
* 值转换器(英文)
* 适用于枚举型转换
*/
Class<? extends ColumnConverter> converter() default ColumnStrategy.AutoConverter.class;
/**
* 是否是用户数组
*/
boolean isUserList() default false;
}
4.然后我们就可以在实际需要进行比较的类上加上该注解【需要进行枚举值转换的属性,我们可以在属性上面的注解中加上converter ,然后注入对应的转换器即可】,示例代码如下
java
@Data
public class DTO {
/**
* 业务名称
*/
@ColumnInfo(cnName = "业务名称", enName = "Business name")
private String bizCode;
/**
* 国别
*/
@ColumnInfo(cnName = "国家", enName = "Country")
private String country;
/**
* 国别
*/
@ColumnInfo(cnName = "到期时间", enName = "Expire time")
private String expireTime;
/**
* 业务状态
*/
@ColumnInfo(cnName = "业务状态", enName = "status", converter = ColumnStrategy.BusinessStatusType.class)
private Integer status;
/**
* 是否校验价格
*/
@ColumnInfo(cnName = "是否校验价格", enName = "Is check price", converter = ColumnStrategy.PriceCheckType.class)
private Integer priceCheckMode;
}
5.现在就可以直接传入修改前后的两个对象,利用反射对其进行修改值的检测了
java
//调用示例
getChangeFields(DTO.class, from, to, descCnList, descEnList);
//具体方法代码如下
private void getChangeFields(Class clazz, Object obj1, Object
obj2, ArrayList<String> cnList, ArrayList<String> enList) {
try {
// 解析对象1和对象2的JSONObject
JSONObject object1 = JSONUtil.parseObj(obj1);
JSONObject object2 = JSONUtil.parseObj(obj2);
if (object1.isEmpty() || object2.isEmpty()) {
return;
}
// 获取该类的所有属性
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 设置属性可访问
field.setAccessible(true);
// 获取属性名
String name = field.getName();
ColumnInfo targetColumnInfo = field.getAnnotation(ColumnInfo.class);
ColumnConverter columnConverter = getColumnConverter(targetColumnInfo);
// 判断对象1和对象2的属性数量是否不为0(如果是创建则object2为null)
// 判断对象1和对象2的属性值是否都不为空(由于有一些属性始终为null,所以需要过滤掉,不然会空指针异常)
Object o1 = object1.get(name);
Object o2 = object2.get(name);
// 判断对象1和对象2的属性值是否不相等
if (ObjectUtil.equals(o1, o2)) {
continue;
}
if (Constants.CHECK_CONVERT_FILED.contains(name)) {
Object cnFrom = ObjectUtil.isNotEmpty(o1) ? columnConverter.cnConverter(o1) : StringPool.EMPTY;
Object cnTo = ObjectUtil.isNotEmpty(o2) ? columnConverter.cnConverter(o2) : StringPool.EMPTY;
Object enFrom = ObjectUtil.isNotEmpty(o1) ? columnConverter.enConverter(o1) : StringPool.EMPTY;
Object enTo = ObjectUtil.isNotEmpty(o2) ? columnConverter.enConverter(o2) : StringPool.EMPTY;
// 添加属性名到列表中
cnList.add(String.format("%s【%s】更新为【%s】", targetColumnInfo.cnName(), cnFrom, cnTo));
enList.add(String.format("%s【%s】 changed to 【%s】", targetColumnInfo.enName(), enFrom, enTo));
} else {
o1 = ObjectUtil.isNotEmpty(o1) ? o1 : StringPool.EMPTY;
o2 = ObjectUtil.isNotEmpty(o2) ? o2 : StringPool.EMPTY;
if (ObjectUtil.isNotEmpty(targetColumnInfo.cnName())) {
cnList.add(String.format("%s【%s】更新为【%s】", targetColumnInfo.cnName(), o1, o2));
}
if (ObjectUtil.isNotEmpty(targetColumnInfo.enName())) {
enList.add(String.format("%s【%s】 changed to 【%s】", targetColumnInfo.enName(), o1, o2));
}
}
}
} catch (Exception e) {
// 获取异常信息详情
log.error("---Failed to check attributes---", e);
}
}