前言

Dozer是一个Java Bean到Java Bean的Mapper,可将数据从一个对象递归复制到另一个对象。Dozer支持简单属性、复杂属性映射,Java中常见集合相互映射和递归映射。

Dozer可以看做是一个对象属性拷贝工具,适用于模型转换,同样的工具还有很多,例如Cglib的BeanCopier、Apache 的PropertyUtils、Spring的BeanUtils。

Dozer与上述工具相比,最大的优势就是支持不同名属性映射。当然,最大的劣势就是性能差。这里附上一张其他博主做性能测试的表格。相关博文

方法 归属 单次耗时[ms] 100万次耗时[ms] 平均耗时[ms]
BeanCopier copy Cglib 0.005071 58.415201 0.000058
BeanUtils copyProperties Spring 0.072082 2155.744378 0.002155
PropertyUtils copyProperties Apache 0.164118 16714.877932 0.016714
DozerBeanMapper map Dozer 0.598338 19158.842820 0.019158

所以,当系统数据量不大、对性能要求不高,或者需要非同名属性映射时可以考虑使用Dozer。

springboot使用dozer pom依赖。

<dependency><groupId>com.github.dozermapper</groupId><artifactId>dozer-spring-boot-starter</artifactId><version>6.5.0</version>
</dependency>

一、Configuration配置

  • 简单配置

    application.yml

    dozer:mapping-files: classpath:dozer/first.xml
    

    dozer.mapping-filesdozer-spring-boot-start自带属性,可以通过application.yml配置,多个用逗号隔开

  • 通配符配置

    默认不支持通配符配置,需要编写配置文件

    dozer:mapping-files: classpath:dozer/*.xml
    
    @Configuration
    public class DozerConfig {@Beanpublic DozerBeanMapperFactoryBean dozerMapper(@Value("${dozer.mapping-files}") Resource[] resources) throws IOException {DozerBeanMapperFactoryBean dozerBeanMapperFactoryBean = new DozerBeanMapperFactoryBean();dozerBeanMapperFactoryBean.setMappingFiles(resources);return dozerBeanMapperFactoryBean;}
    }
    
  • mapping配置文件示例

    <?xml version="1.0" encoding="UTF-8"?>
    <mappings xmlns="http://dozermapper.github.io/schema/bean-mapping"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping http://dozermapper.github.io/schema/bean-mapping.xsd"><mapping><class-a>org.dozer.vo.TestObject</class-a><class-b>org.dozer.vo.TestObjectPrime</class-b><field><a>one</a><b>onePrime</b></field></mapping>
    </mappings>
    

二、工具类

@Component
public class DozerUtil {private static Mapper dozerMapper;@Autowiredpublic void setDozerMapper(Mapper dozerMapper) {DozerUtil.dozerMapper = dozerMapper;}/*** 构造新的destinationClass实例对象,通过source对象中的字段内容* 映射到destinationClass实例对象中,并返回新的destinationClass实例对象。** @param source           源数据对象* @param destinationClass 要构造新的实例对象Class*/public static <T> T map(Object source, Class<T> destinationClass) {return dozerMapper.map(source, destinationClass);}/*** 将对象source的所有属性值拷贝到对象destination中.** @param source            对象source* @param destinationObject 对象destination*/public static void map(Object source, Object destinationObject) {dozerMapper.map(source, destinationObject);}/*** List数据源映射** @param sourceList* @param destinationClass* @param <T>* @return List<T>*/public static <T> List<T> mapList(Collection sourceList, Class<T> destinationClass) {List destinationList = new ArrayList<>();for (Iterator iterator = sourceList.iterator(); iterator.hasNext(); ) {Object sourceObject = iterator.next();Object destinationObject = dozerMapper.map(sourceObject, destinationClass);destinationList.add(destinationObject);}return destinationList;}

三、常用的几种映射

  • Bean到Bean

    Bean和Bean之间映射,这是最常见的映射。Dozer默认同名映射,即不用配置文件就可以实现Bean之间的同名映射。使用Mapping配置文件即可实现非同名属性的映射。

  • Bean List到Bean List

    实际上还是Bean之间的映射,将srcList中Bean映射完后装入destList中

  • Date到String

    • 单个字段

      <field><a date-format="yyyy-MM-dd HH:mm:ss">dateObject</a><b>dateString</b>
      </field>
      
    • 单个类所有Date字段

      <mapping date-format="yyyy-MM-dd HH:mm:ss">
      </mapping>
      
  • HashMap到Bean

    hashMap可以通过将key配置成Bean的field名,和Bean映射

四、高级功能

  • 自定义转换器

    • 自定义类型转换器需要实现com.github.dozermapper.core.CustomConverter接口或者继承com.github.dozermapper.core.DozerConverter

    • 以CustomConverter示例:Enum映射String

      public enum Color {RED("red"), GREEN("green"), YELLOW("yellow");private String value;Color(String value) {this.value = value;}public static Color newInstance(String color) throws Exception {switch (color) {case "red" : return RED;case "green": return GREEN;case "yellow": return YELLOW;default: throw new Exception("unknow color:" + color);}}@Overridepublic String toString() {return value;}
      }
      
      @Data
      public class FlowerVo {private Integer id;private String purchaseDateStr;private String colorStr;
      }
      
      @Data
      public class Flower {private Integer id;private Date purchaseDate;private Color color;
      }
      
      public class EnumColorCustomConverter implements CustomConverter {@Overridepublic Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, Class<?> destinationClass, Class<?> sourceClass) {if (sourceFieldValue == null) {return null;}if (sourceFieldValue instanceof Color) {return sourceFieldValue.toString();} if (sourceFieldValue instanceof String && destinationClass.equals(Color.class)) {try {return Color.newInstance((String)sourceFieldValue);} catch (Exception e) {e.printStackTrace();}} else{throw new MappingException("Converter EnumColorCustomConverter "+ "used incorrectly. Arguments passed in were:"+ sourceFieldValue);}return  null;}
      }
      
      <mapping><class-a>com.aabond.entity.Flower</class-a><class-b>com.aabond.entity.FlowerVo</class-b><field><a >purchaseDate</a><b date-format="yyyy-MM-dd HH:mm:ss">purchaseDateStr</b></field><field custom-converter="com.aabond.converter.EnumColorCustomConverter"><a>color</a><b>colorStr</b></field>
      </mapping>
      
      @Test
      public void testDozer() {Flower flower = new Flower();flower.setId(1);flower.setPurchaseDate(new Date());flower.setColor(Color.RED);FlowerVo f = DozerUtil.map(flower, FlowerVo.class);System.out.println(f);//assertThat(map, isA(Flower.class));}
      
  • 更多配置
    关于XML配置,更详细信息可以查看官方文档,下面介绍一些常用的配置

    • Date和String 全局映射

      <mappings><configuration><date-format>yyyy-MM-dd HH:mm:ss</date-format><!-- more --></configuration>
      </mappings>
      
    • 遇到错误策略 默认true

      <stop-on-errors>true</stop-on-errors>
      
    • 同名属性映射 默认true

      <wildcard>true</wildcard>
      
    • 字符串Trim

      <trim-strings>false</trim-strings>
      
    • 全局自定义转换器

      <custom-converters> <converter type="org.dozer.converters.TestCustomConverter" ><class-a>org.dozer.vo.TestCustomConverterObject</class-a><class-b>another.type.to.Associate</class-b></converter>
      </custom-converters>
      
    • null值不映射

      <field map-null="false"><a>oneFoo2</a><b>oneFooPrime2</b>
      </field>
      
    • 单项映射
      dozer默认是双向映射,可以通过配置改成单项映射

      • 支持字段单项映射

        <field type="one-way"><a>oneFoo2</a><b>oneFooPrime2</b>
        </field>
        
      • 支持类单项映射

        <mapping type="one-way">
        </mapping>
        
    • 复制引用

      • Dozer支持复制引用

        <field copy-by-reference="true"><a>copyByReference</a><b>copyByReferencePrime</b>
        </field>
        
      • 支持全局配置

        <configuration><copy-by-references><copy-by-reference>com.github.dozermapper.core.vo.NoExtendBaseObjectGlobalCopyByReference</copy-by-reference></copy-by-references>
        </configuration>
        

参考:

  • https://blog.csdn.net/u012534326/article/details/102611483

  • http://dozer.sourceforge.net/dozer-user-guide.pdf

  • https://dozermapper.github.io/gitbook/

SpringBoot学习小结之Dozer相关推荐

  1. SpringBoot学习小结之Redis

    文章目录 前言 一.SpringBoot使用Redis 1.1 pom依赖 1.2 两种连接方案 1.3 配置 1.4 简单使用 二.各种场景 2.1 缓存数据 2.2 分布式锁 2.2.1 通过se ...

  2. SpringBoot学习小结之Elasticsearch

    文章目录 一.Elasticsearch 1.1 用途 1.2 和Apache solr对比 1.3 基本概念 1.4 基本使用 1.5 Java API 二.SpringBoot 2.1 版本 2. ...

  3. SpringBoot(学习笔记)

    SpringBoot学习笔记 从今天开始就进入微服务阶段 一些小问题 1.HelloWorld 1.1回顾什么是Spring 1.2什么是SpringBoot 1.3微服务架构 2.第一个Spring ...

  4. Springboot学习笔记(二)Web开发

    前言: 学习B站UP主狂神说视频笔记整理视频链接 狂神笔记链接 上篇笔记链接-Springboot学习笔记(一)快速上手 Web开发 静态资源 在以往的SpringMVC中所有静态资源或者页面应该放在 ...

  5. springboot学习文档

    SpringBoot学习文档 首先真的特别感谢同学的分享以及老师的整理,让我成功入门了springboot的. 一.介绍 小结: - SpringBoot并不是一个新的开发语言- Spring Boo ...

  6. SpringBoot 学习笔记

    SpringBoot 学习笔记 文章目录 SpringBoot 学习笔记 1. SpringBoot简介 1.1 什么是Spring 1.2 Spring 是如何简化Java开发的 1.3 什么是 S ...

  7. 狂神说——SpringBoot学习

    spring官网 SpringBoot官网 spring-security版本下载 狂神官网学习 也可以搜索B站 (狂神说) 学习网站:https://www.bilibili.com/video/B ...

  8. Python - 输出格式 (学习小结)

    Python - 输出格式 (学习小结) Bu.xing 利用现代手段,创建学习家园 ​关注他 1 人赞同了该文章 Python 输出格式 我们常说的输出格式分两种含义: # 一种是指数据在屏幕上的显 ...

  9. Page 的生命周期学习小结

    (以前我在 csdn 写的翻译文章,现在转到这里来.) Page 的生命周期学习小结 原文链接:Page Events: Order and PostBack 作者:Paul Wilson 翻译:木野 ...

最新文章

  1. ImportError: cannot import name ‘DtypeArg‘ from ‘pandas
  2. oschina多媒体工具
  3. centos下升级glib
  4. Python第三章-字符串
  5. STM32外部中断与各通道对应关系
  6. 【♻️markdown之一次编写,到处使用♻️】markdown文件转word
  7. C 图像处理 颜色相关宏定义
  8. JS转字符 判断数字等
  9. 6.23 NIUDAY 深圳站 | 从新零售到金融,Follow 技术大咖一起探索人工智能应用的无限可能...
  10. 远程仓库---从远程库克隆
  11. 相同Ip 不同端口配置Nginx反向代理Apache
  12. 微软服务器系统桌面无图标,开机桌面没有图标的几种解决方法
  13. 关闭rhel 6.5的selinux
  14. 运动目标跟踪(一)--搜索算法预测模型之KF,EKF,UKF
  15. Linux系统编程 -- 死锁
  16. 手动方式安装 eclipse 的svn插件 Subversive和 Subversive SVN Connectors
  17. [wordpress搬家]马来西亚 你好
  18. android空间深度清理,安卓手机垃圾深度清理技巧
  19. unity学习、unity培训、unity企业培训、U3D资源、U3D培训视频U3D教程、U3D常见问题、U3D项目源码
  20. iOS 系统方法获取当前位置经纬度

热门文章

  1. 安装到树莓派c语言编程ide,【玩树莓】编程篇(四)在树莓派2上运行Cloud9 IDE服务器...
  2. 树莓派的GPIO编程
  3. 如何将微课应用到计算机教学,如何将微课应用于高校计算机教学中
  4. Unity音频采样器(用于Unity音乐可视化)
  5. python打包中文报错,解决python3+Gooey使用pyinstaller打包时无法输出中文的问题
  6. 阿里系utdid和友盟冲突解决方案
  7. 工作感悟-窝囊男人的特点
  8. 密码学实验_8_本原根计算(python 实现)
  9. UE4 蓝图编程官网初级练习目录
  10. 星际官方小说:《刀锋女王》