Dozer 轻松高效玩转DTO(Data Transfer Object)
现状
对于分布式系统,需要在不同系统之间传递与转换域对象。因为我们不希望外部公开内部域对象,也不允许外部域对象渗入系统。传统上,数据对象之间的映射通过手工编码(getter/setter)的方式实现,或对象组装器(或转换器)来解决。我们可能会开发某种自定义映射框架来满足我们的映射转换需求,但这一切都显得不够灵巧。
Dozer
Dozer 是 Java Bean 到 Java Bean 映射器,它以递归方式将数据从一个对象复制到另一个对象。
通常,这些 Java Bean 将具有不同的复杂类型。Dozer 支持简单属性映射,复杂类型映射,双向映射,隐式和显式映射以及递归映射。
Dozer不仅支持属性名称之间的映射,还支持在类型之间自动转换。大多数转换方案都是开箱即用的,但 Dozer 还允许您通过 XML / API 的方式指定自定义转换。
下图描绘了 Dozer 可以插入到架构中的一些常见区域。请注意,它通常用于边界(进入/退出)。 Dozer 将确保数据库中的内部域对象不会流入外部表示层或外部使用者。它还可以帮助将域对象映射到外部 API 调用,反之亦然,现在不用纠结这个图,看完下面的测试用例回看该图,柳暗花明, 文末有完整测试用例
集成 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>
本文主要讲述在 Spring Boot 下如何通过 Dozer 帮助我们搞定 DTO 那点事
使用 Dozer
默认使用
Dozer starter 默认为我们注入了 Dozer Mapper,可以直接使用,另外,文章中所有测试用例中使用 Lombok 注解简化代码 新建 StudentDomain.java 类
@Data @NoArgsConstructor @AllArgsConstructor public class StudentDomain { // 身份ID private Long id; // 姓名 private String name; // 年龄 private Integer age; // 电话 private String mobile; }
新建 StudentVo.java 类,内容同 StudentDomain.java 编写测试用例:
@Autowired private Mapper dozerMapper; @Test public void testDefault(){ StudentDomain studentDomain = new StudentDomain(1024L, "tan日拱一兵", 18, "13996996996"); StudentVo studentVo = dozerMapper.map(studentDomain, StudentVo.class); log.info("StudentVo: [{}]", studentVo.toString()); studentVo.setAge(16); log.info("StudentDomain: [{}]", dozerMapper.map(studentVo, StudentDomain.class)); }
运行结果:
StudentVo: [StudentVo(id=1024, name=tan日拱一兵, age=18, mobile=13996996996)] StudentDomain: [StudentDomain(id=1024, name=tan日拱一兵, age=16, mobile=13996996996)]
结论:
Dozer 默认支持同名 field 的双向映射,即隐式映射 如果仅满足这点需求,就没必要写该文章了,应用 Dozer 也为了满足我们更多定制化的需求
定制化使用
为满足更多的转换需求,我们需要针对 Dozer 定制化,即需要我们声明自己的 Mapper,新建 DozerConfig.java 类
@Configuration public class DozerConfig { @Bean public Mapper dozerMapper(){ Mapper mapper = DozerBeanMapperBuilder.create() //指定 dozer mapping 的配置文件(放到 resources 类路径下即可),可添加多个 xml 文件,用逗号隔开 .withMappingFiles("dozerBeanMapping.xml") .withMappingBuilder(