BeanUtils——JavaBean相互杏彩平臺帶保險理賠倉轉換及字典翻譯
其中功能包括:
翻譯JavaBean中帶有@CacheFormat的屬性
/**
- 翻譯當前類中需要翻譯的字典值
-
@param source 待翻譯的對象
*/
public static <T> void dataFormatter(T source) {//判斷原對象是否為null
Assert.notNull(source, "待翻譯的原對象不能為null");//獲取所有屬性並翻譯字典
Field[] declaredFields = source.getClass().getDeclaredFields();//翻譯字典:找出所有含有@CacheFormatter的屬性
br/>//翻譯字典:找出所有含有@CacheFormatter的屬性
br/>//排除沒有註解@CacheFormatter的字段
//翻譯
doFormatter(fieldStream, source, source.getClass());
}
翻譯List/**
- 翻譯當前集合類中需要翻譯的字典值
-
@param sources 待翻譯的集合對象
*/
public static <T> void dataFormatter(List<T> sources) {//當翻譯的集合為空時,返回空的集合
if (sources == null || sources.isEmpty()) {
return;
}Class targetClass = sources.get(0).getClass();
//獲取所有屬性並翻譯字典
Field[] declaredFields = targetClass.getDeclaredFields();//翻譯字典:找出所有含有@CacheFormat的屬性集合
br/>//翻譯字典:找出所有含有@CacheFormat的屬性集合
br/>//排除沒有註解@CacheFormat的字段
.collect(Collectors.toList());
//循環列表(並行操作)
//翻譯
doFormatter(formatterFields.stream(), target, targetClass);
});
}
Entity 與DTO互轉
/**
- 把原對象轉換成目標類的對象,並翻譯目標類的屬性字典
- 只針對目標類沒有範型或者範型與原對象一樣
- @param source 原對象
- @param targetClass 目標類
-
@return 目標對象
*/
public static <T> T dataConvert(Object source, Class<T> targetClass) {Assert.isTrue(source != null && targetClass != null, "原對象或目標class不能為null");
T target = BeanUtils.instantiateClass(targetClass);
//把目標對象的屬性設置成原對象中對應的屬性
BeanUtils.copyProperties(source, target);dataFormatter(target);
return target;
}
/**
- 實體屬性互轉
- @param source 原對象
- @param target 目標對象
-
@return 目標對象
*/
public static <T> T dataObjConvert(Object source, T target) {Assert.isTrue(source != null && target != null, "待轉換的原對象或目標對象不能為null");
//轉換
BeanUtils.copyProperties(source, target);
//翻譯
dataFormatter(target);
return target;
}
List
/**
- 批量把原對象轉換成目標對象,並翻譯目標對象的屬性字典
- 如果想返回指定類型的集合即List的子類,參考{@link HyBeanUtils#dataConverts2}
- @param sources 原對象集合
- @param targetClass 目標對象的類
-
@return 返回轉換後的目標集合
*/
public static <T, E> List<T> dataConverts(List<E> sources, Class<T> targetClass) {Assert.notNull(targetClass, "轉換的目標Class不能為null");
//當翻譯的集合為空時,返回空的集合
if (sources == null || sources.isEmpty()) {
List<T> targetList = new ArrayList<>();
return targetList;
}
//獲取原集合的類型
Class<? extends List> aClass = sources.getClass();
//目標集合
List<T> targetList = BeanUtils.instantiateClass(aClass);//把目標對象的屬性設置成原對象中對應的屬性(並行操作)
sources.parallelStream().forEach(item -> {
T target = BeanUtils.instantiateClass(targetClass);
BeanUtils.copyProperties(item, target);
targetList.add(target);
});//翻譯字典
dataFormatter(targetList);return targetList;
}
這個是List轉換的升級版 T
/**
- 返回指定類型的方法,這裏的類型必須是List的子類
- 批量把原對象轉換成目標對象,並翻譯目標對象的屬性字典,
- @param sources 原對象集合
- @param targetClass 目標對象的類
- @param returnType 返回值類型
-
@return 返回轉換後的目標集合
*/
public static <T, E, R extends List<T>> R dataConverts2(List<E> sources, Class<T> targetClass, Class<R> returnType) {Assert.notNull(targetClass, "轉換的目標Class不能為null");
Assert.notNull(returnType, "返回值類型Class不能為null");//當翻譯的集合為空時,返回空的集合
if (sources == null || sources.isEmpty()) {
return null;
}
//目標集合
R targetList = BeanUtils.instantiateClass(returnType);//把目標對象的屬性設置成原對象中對應的屬性(並行操作)
sources.parallelStream().forEach(item -> {
T target = BeanUtils.instantiateClass(targetClass);
BeanUtils.copyProperties(item, target);
targetList.add(target);
});//翻譯字典
dataFormatter(targetList);return targetList;
}
上述所用到的公共方法
/**
- 對目標類需要翻譯的字段進行翻譯
- @param stream
- @param target 目標對象
-
@param targetClass 目標對象類
*/
private static <T> void doFormatter(Stream<Field> stream, Object target, Class<T> targetClass) {//排除目標對象中字段值為null的字段
stream.filter(field -> {
PropertyDescriptor propertyDescriptor = BeanUtils.getPropertyDescriptor(targetClass, field.getName());
Object invoke = null;
try {
invoke = propertyDescriptor.getReadMethod().invoke(target, new Object[]{});
} catch (IllegalAccessException e) {
logger.warn("待翻譯的字段的get是無法訪問的", e);
} catch (InvocationTargetException e) {
logger.warn("調用待翻譯的字段的get方法時報錯", e);
} catch (Exception e) {
logger.warn("確保屬性有get,set方法", e);
}
return invoke != null;
//遍歷需要翻譯的字段
}).forEach(field -> {
CacheFormat annotation = field.getAnnotation(CacheFormat.class);//緩存系統編號,如果不指定則默認為當前系統編號 String systemCode = "system_code"; if (StringUtils.isNotBlank(annotation.systemCode())) { systemCode = annotation.systemCode(); } //緩存key,如果不指定,則默認為字段名稱 String key = annotation.key(); if (StringUtils.isBlank(key)) { key = field.getName(); } //判斷註解@CacheFormatter是否指定把字典翻譯到另一個字段上 String formatterField = annotation.destination(); if (StringUtils.isBlank(formatterField)) { //當註解中不指定其他字段時,默認翻譯到加註解的屬性上 formatterField = field.getName(); } try { PropertyDescriptor orginPropertyDescriptor = BeanUtils.getPropertyDescriptor(targetClass, field.getName()); Object value = orginPropertyDescriptor.getReadMethod().invoke(target, new Object[]{}); //設置目標字段值 PropertyDescriptor propertyDescriptor = BeanUtils.getPropertyDescriptor(targetClass, formatterField); //取緩存 String cacheValue = RedisUtils.hget(systemCode +":valueset:" + key, value + ""); //如果數據字典中查詢不到,則取業務緩存中取 if (StringUtils.isBlank(cacheValue)) { cacheValue = RedisUtils.hget(systemCode + ":valueset:" + key, value + ""); } Assert.hasLength(cacheValue, "在緩存" + key + "中沒有找到" + value + "對應的緩存"); //設置緩存值到屬性字段中 propertyDescriptor.getWriteMethod().invoke(target, cacheValue); } catch (IllegalAccessException e) { logger.warn("待翻譯的字段的set是無法訪問的", e); } catch (InvocationTargetException e) { logger.warn("調用待翻譯的字段的set方法時報錯", e); } catch (Exception e) { e.printStackTrace(); logger.warn("調用待翻譯的字段的set方法時報錯,推測類型不匹配", e); }
});
}
註解 CacheFormat
@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)
br/>@Retention(RetentionPolicy.RUNTIME)
public @interface CacheFormat {
/**
- 緩存key
-
@return
*/
String key();/**
- 指定翻譯值存放字段, 例如:userType的翻譯結果放到userTypeName上
-
@return
*/
String destination() default "";/**
- 系統編號
- @return
*/
String systemCode() default "";
註意:該翻譯只關註第一層即當前對象的屬性,並不會遞歸翻譯
比如:當前類有一個屬性為對象實例,該對象也有被@CacheFormat註解的屬性
這時該工具類不會去翻譯這個屬性中的屬性,需要開發者先用當前工具類轉換該屬性
然後再設置到目標類中
BeanUtils——JavaBean相互杏彩平臺帶保險理賠倉轉換及字典翻譯