前言
- 在项目中由于需要将bean转DTO转VO,或者Map到bean等场景都涉及到类对象属性拷贝,如果字段少的话,手动set也是ok的,要是多的话就嘿嘿嘿了,还是懒点好
- 对比了比较热门的工具如:BeanCopier、BeanUtils、DozerBeanMapper、PropertyUtils,
不得不说BeanCopier性能是真的强,由于本人项目中VO存在多层嵌套的情况,所以考虑使用DozerBeanMapper来实现,因为它支持深拷贝,
问题
在String转LocalDateTime类型时,报错:Unsupported source object type: class java.lang.String
,排查了一下问题所在:
报错的逻辑是:
if (TemporalAccessor.class.isAssignableFrom(srcObjectClass)) {
Method method = destClass.getDeclaredMethod("from", TemporalAccessor.class);
return method.invoke(null, (TemporalAccessor)srcObject);
} else if (String.class.isAssignableFrom(srcObjectClass) && formatter != null) {
Method method = destClass.getDeclaredMethod("parse", CharSequence.class, DateTimeFormatter.class);
return method.invoke(null, srcObject, formatter);
} else {
throw new ConversionException(String.format("Unsupported source object type: %s", srcObjectClass), null);
}
代码拷贝自AbstractJava8DateTimeConverter#convert
显然formatter为null导致,
解决方案:
一:配置formatter
<field>
<a date-format="MM/dd/yyyy HH:mm:ss:SS">dateString</a>
<b>dateObject</b>
</field>
具体请查看官网[http://dozer.sourceforge.net/documentation/stringtodatemapping.html]
二:通过CustomFieldMapper来实现
代码如下:
private static final Mapper MAPPER = DozerBeanMapperBuilder.create().withCustomFieldMapper((source, destination, sourceFieldValue, classMap, fieldMapping) -> {
Class<?> destFieldType = fieldMapping.getDestFieldType(BuilderUtil.unwrapDestClassFromBuilder(destination));
if (LocalDateTime.class.getTypeName().equals(destFieldType.getTypeName()) && String.class.getTypeName().equals(sourceFieldValue.getClass().getTypeName())) {
fieldMapping.writeDestValue(destination, LocalDateTime.parse((CharSequence) sourceFieldValue, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
return true;
}
return false;
}).build();
当然,也可以通过Spring
的容器来管理这个Singleton