1.现状
对于分布式系统,需要在不同系统之间传递与转换域对象。因为我们不希望外部公开内部域对象,也不允许外部域对象渗入系统。传统上,数据对象之间的映射通过手工编码(getter/setter)的方式实现,或对象组装器(或转换器)来解决。我们可能会开发某种自定义映射框架来满足我们的映射转换需求,但这一切都显得不够灵巧。
Dozer
Dozer 是 Java Bean 到 Java Bean 映射器,它以递归方式将数据从一个对象复制到另一个对象。
通常,这些 Java Bean 将具有不同的复杂类型。Dozer 支持简单属性映射,复杂类型映射,双向映射,隐式和显式映射以及递归映射。
Dozer不仅支持属性名称之间的映射,还支持在类型之间自动转换。大多数转换方案都是开箱即用的,但 Dozer 还允许您通过 XML / API 的方式指定自定义转换。
下图描绘了 Dozer 可以插入到架构中的一些常见区域。请注意,它通常用于边界(进入/退出)。 Dozer 将确保数据库中的内部域对象不会流入外部表示层或外部使用者。它还可以帮助将域对象映射到外部 API 调用,反之亦然,现在不用纠结这个图,看完下面的测试用例回看该图,柳暗花明, 文末有完整测试用例
2.集成 Dozer
使用 Dozer 的方式很简单,如果你使用 Maven,添加依赖到 pom.xml 中即可
<dependency>
<groupId>com.github.dozermapper</groupId>
<artifactId>dozer-core</artifactId>
<version>6.4.0</version>
</dependency>
如果你使用 Spring Boot,引入 Dozer starter 即可:
<dependency>
<groupId>com.github.dozermapper</groupId>
<artifactId>dozer-spring-boot-starter</artifactId>
<version>6.2.0</version>
</dependency>
3,使用 Dozer
默认使用
Dozer starter 默认为我们注入了 Dozer Mapper,可以直接使用,另外,文章中所有测试用例中使用 Lombok 注解简化代码
3.1)当属姓名不通的,通过直接映射
第1步,不同属性名的在被转换bean上(Do)注解@Mapping(“vo里该字段名称”)
list转换:
package com.xunxiao.common.utils;
import com.github.dozermapper.core.DozerBeanMapperBuilder;
import com.github.dozermapper.core.Mapper;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
/**
* dozer 转换器
* @author zq
*/
@Component
public class GeneralConvertor {
//持有Dozer单例, 避免重复创建DozerMapper消耗资源.
@Resource
public static final Mapper mapper = DozerBeanMapperBuilder.buildDefault();
/**
* List 实体类 转换器
*
* @param source 原数据
* @param clz 转换类型
* @param <T>
* @param <S>
* @return
*/
public <T, S> List<T> convertor(List<S> source, Class<T> clz) {
if (source == null) return null;
List<T> map = new ArrayList<>();
for (S s : source) {
map.add(mapper.map(s, clz));
}
return map;
}
/**
* Set 实体类 深度转换器
*
* @param source 原数据
* @param clz 目标对象
* @param <T>
* @param <S>
* @return
*/
public <T, S> Set<T> convertor(Set<S> source, Class<T> clz) {
if (source == null) return null;
Set<T> set = new TreeSet<>();
for (S s : source) {
set.add(mapper.map(s, clz));
}
return set;
}
/**
* 实体类 深度转换器
*
* @param source
* @param clz
* @param <T>
* @param <S>
* @return
*/
public <T, S> T convertor(S source, Class<T> clz) {
if (source == null) return null;
return mapper.map(source, clz);
}
public void convertor(Object source, Object object) {
mapper.map(source, object);
}
public <T> void copyConvertor(T source, Object object) {
mapper.map(source, object);
}
}
List<InterxxxxxxxxxxxxxtItemDo> interestDoList = intxxxxxxxxxxxxxntItemService.getInterexxxxxxxxxst(ixxxxxxxxntItemPage.getIxxxxxxxd());
List<InterxxxxxxxxxxxxxmVo> resultVoList = null;
//Do列表不为null,进行Do->Vo转换
if(interestDoList!=null){
resultVoList = this.convertor.convertor(interestDoList, InterestContentItemVo.class);
}else{
return CommonPage.failed("xxxxxxxxxx");
}