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(
经验分享 程序员 微信小程序 职场和发展