转自https://www.jianshu.com/p/bf8f0e8aee23
概述
Dozer是什么?
Dozer是一个JavaBean映射工具库。
它支持简单的属性映射,复杂类型映射,双向映射,隐式显式的映射,以及递归映射。
它支持三种映射方式:注解、API、XML。
它是开源的,遵从Apache 2.0 协议
安装
引入jar包
maven方式
如果你的项目使用maven,添加以下依赖到你的pom.xml即可:
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.4.0</version>
</dependency>
非maven方式
如果你的项目不使用maven,那就只能发扬不怕苦不怕累的精神了。
使用Dozer需要引入Dozer的jar包以及其依赖的第三方jar包。
Eclipse插件
Dozer有插件可以在Eclipse中使用(不知道是否好用,反正我没用过)
插件地址: http://dozer.sourceforge.net/eclipse-plugin
使用
将Dozer引入到工程中后,我们就可以来小试一番了。
实践出真知,先以一个最简单的例子来展示Dozer映射的处理过程。
准备
我们先准备两个要互相映射的类
NotSameAttributeA.java
public class NotSameAttributeA {
private long id;
private String name;
private Date date;
// 省略getter/setter
}
NotSameAttributeB.java
public class NotSameAttributeB {
private long id;
private String value;
private Date date;
// 省略getter/setter
}
这两个类存在属性名不完全相同的情况:name 和 value。
Dozer的配置
为什么要有映射配置?
如果要映射的两个对象有完全相同的属性名,那么一切都很简单。
只需要直接使用Dozer的API即可:
Mapper mapper = new DozerBeanMapper();
DestinationObject destObject =
mapper.map(sourceObject, DestinationObject.class);
但实际映射时,往往存在属性名不同的情况。
所以,你需要一些配置来告诉Dozer应该转换什么,怎么转换。
注:官网着重建议:在现实应用中,最好不要每次映射对象时都创建一个Mapper
实例来工作,这样会产生不必要的开销。如果你不使用IoC容器(如:spring)来管理你的项目,那么,最好将Mapper
定义为单例模式。
映射配置文件
在src/test/resources
目录下添加dozer/dozer-mapping.xml
文件。<mapping>
标签中允许你定义<class-a>
和<class-b>
,对应着相互映射的类。<field>
标签里定义要映射的特殊属性。需要注意<a>
和<class-a>
对应,<b>
和<class-b>
对应,聪明的你,猜也猜出来了吧。
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozer.sourceforge.net
http://dozer.sourceforge.net/schema/beanmapping.xsd">
<mapping date-format="yyyy-MM-dd">
<class-a>org.zp.notes.spring.common.dozer.vo.NotSameAttributeA</class-a>
<class-b>org.zp.notes.spring.common.dozer.vo.NotSameAttributeB</class-b>
<field>
<a>name</a>
<b>value</b>
</field>
</mapping>
</mappings>
与Spring整合
配置 DozerBeanMapperFactoryBean
在src/test/resources
目录下添加spring/spring-dozer.xml
文件。
Dozer与Spring的整合很便利,你只需要声明一个DozerBeanMapperFactoryBean
,
将所有的dozer映射配置文件作为属性注入到mappingFiles
,DozerBeanMapperFactoryBean
会加载这些规则。
spring-dozer.xml文件范例
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
default-autowire="byName" default-lazy-init="false">
<bean id="mapper" class="org.dozer.spring.DozerBeanMapperFactoryBean">
<property name="mappingFiles">
<list>
<value>classpath*:dozer/dozer-mapping.xml</value>
</list>
</property>
</bean>
</beans>
自动装配
至此,万事具备,你只需要自动装配mapper
。
RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/spring-dozer.xml"})
@TransactionConfiguration(defaultRollback = false)
public class DozerTest extends TestCase {
@Autowired
Mapper mapper;
@Test
public void testNotSameAttributeMapping() {
NotSameAttributeA src = new NotSameAttributeA();
src.setId(007);
src.setName("邦德");
src.setDate(new Date());
NotSameAttributeB desc = mapper.map(src, NotSameAttributeB.class);
Assert.assertNotNull(desc);
}
}
运行一下单元测试,绿灯通过。
Dozer支持的数据类型转换
Dozer可以自动做数据类型转换。当前,Dozer支持以下数据类型转换(都是双向的)
-
Primitive to Primitive Wrapper
原型(int、long等)和原型包装类(Integer、Long)
-
Primitive to Custom Wrapper
原型和定制的包装
-
Primitive Wrapper to Primitive Wrapper
原型包装类和包装类
-
Primitive to Primitive
原型和原型
-
Complex Type to Complex Type
复杂类型和复杂类型
-
String to Primitive
字符串和原型
-
String to Primitive Wrapper
字符串和原型包装类
-
String to Complex Type if the Complex Type contains a String constructor
字符串和有字符串构造器的复杂类型(类)
-
String to Map
字符串和Map
-
Collection to Collection
集合和集合
-
Collection to Array
集合和数组
-
Map to Complex Type
Map和复杂类型
-
Map to Custom Map Type
Map和定制Map类型
-
Enum to Enum
枚举和枚举
-
Each of these can be mapped to one another: java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, java.util.Calendar, java.util.GregorianCalendar
这些时间相关的常见类可以互换:java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, java.util.Calendar, java.util.GregorianCalendar
-
String to any of the supported Date/Calendar Objects.
字符串和支持Date/Calendar的对象
-
**Objects containing a toString() method that produces a long representing time in (ms) to any supported Date/Calendar object. **
如果一个对象的toString()方法返回的是一个代表long型的时间数值(单位:ms),就可以和任何支持Date/Calendar的对象转换。
Dozer的映射配置
在前面的简单例子中,我们体验了一把Dozer的映射流程。但是两个类进行映射,有很多复杂的情况,相应的,你也需要一些更复杂的配置。
Dozer有三种映射配置方式:
- 注解方式
- API方式
- XML方式
用注解来配置映射
Dozer 5.3.2版本开始支持注解方式配置映射(只有一个注解:@Mapping
)。可以应对一些简单的映射处理,复杂的就玩不转了。
看一下@Mapping
的声明就可以知道,这个注解只能用于元素和方法。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface Mapping {
String value() default "";
}
让我们来试试吧:
TargetBean.java
public class SourceBean {
private Long id;
private String name;
@Mapping("binaryData")
private String data;
@Mapping("pk")
public Long getId() {
return this.id;
}
//其余getter/setter方法略
}
TargetBean.java
public class TargetBean {
private String pk;
private String name;
private String binaryData;
//getter/setter方法略
}
定义了两个相互映射的Java类,只需要在源类中用@Mapping
标记和目标类中对应的属性就可以了。
@Test
public void testAnnotationMapping() {
SourceBean src = new SourceBean();
src.setId(7L);
src.setName("邦德");
src.setData("00000111");
TargetBean desc = mapper.map(src, TargetBean.class);
Assert.assertNotNull(desc);
}
测试一下,绿灯通过。
官方文档说,虽然当前版本(文档的版本对应Dozer 5.5.1)仅支持@Mapping
,但是在未来的发布版本会提供其他的注解功能,那就敬请期待吧(再次吐槽一下:一年多没更新了)。
用API来配置映射
个人觉得这种方式比较麻烦,不推荐,也不想多做介绍,就是这么任性。
用XML来配置映射
需要强调的是:如果两个类的所有属性都能很好的互转,可以你中有我,我中有你,不分彼此,那么就不要画蛇添足的在xml中去声明映射规则了。
属性名不同时的映射(Basic Property Mapping)
Dozer会自动映射属性名相同的属性,所以不必添加在xml文件中。
<field>
<a>one</a>
<b>onePrime</b>
</field>
字符串和日期映射(String to Date Mapping)
字符串在和日期进行映射时,允许用户指定日期的格式。
格式的设置分为三个作用域级别:
属性级别
对当前属性有效(这个属性必须是日期字符串)
<field>
<a date-format="MM/dd/yyyy HH:mm:ss:SS">dateString</a>
<b>dateObject</b>
</field>
类级别
对这个类中的所有日期相关的属性有效
<mapping date-format="MM-dd-yyyy HH:mm:ss">
<class-a>org.dozer.vo.TestObject</class-a>
<class-b>org.dozer.vo.TestObjectPrime</class-b>
<field>
<a>dateString</a>
<b>dateObject</b>
</field>
</mapping>
全局级别
对整个文件中的所有日期相关的属性有效。
<mappings>
<configuration>
<date-format>MM/dd/yyyy HH:mm</date-format>
</configuration>
<mapping wildcard="true">
<class-a>org.dozer.vo.TestObject</class-a>
<class-b>org.dozer.vo.TestObjectPrime</class-b>
<field>
<a>dateString</a>
<b>dateObject</b>
</field>
</mapping>
</mappings>
集合和数组映射(Collection and Array Mapping)
Dozer可以自动处理以下类型的双向转换。
- List to List
- List to Array
- Array to Array
- Set to Set
- Set to Array
- Set to List
使用hint
如果使用泛型或数组,没有必要使用hint。
如果不使用泛型或数组。在处理集合或数组之间的转换时,你需要用hint
指定目标列表的数据类型。
若你不指定hint
,Dozer将认为目标集合和源集合的类型是一致的。
使用Hints的范例:
<field>
<a>hintList</a>
<b>hintList</b>
<b-hint>org.dozer.vo.TheFirstSubClassPrime</b-hint>
</field>
累计映射和非累计映射(Cumulative vs. Non-Cumulative List Mapping)
如果你要转换的目标类已经初始化,你可以选择让Dozer添加或更新对象到你的集合中。
而这取决于relationship-type
配置,默认是累计。
它的设置有作用域级别:
- 全局级
<mappings>
<configuration>
<relationship-type>non-cumulative</relationship-type>
</configuration>
</mappings>
- 类级别
<mappings>
<mapping relationship-type="non-cumulative">
<!-- 省略 -->
</mapping>
</mappings>
- 属性级别
<field relationship-type="cumulative">
<a>hintList</a>
<b>hintList</b>
<a-hint>org.dozer.vo.TheFirstSubClass</a-hint>
<b-hint>org.dozer.vo.TheFirstSubClassPrime</b-hint>
</field>
移动孤儿(Removing Orphans)
这里的孤儿是指目标集合中存在,但是源集合中不存在的元素。
你可以使用remove-orphans
开关来选择是否移除这样的元素。
<field remove-orphans="true">
<a>srcList</a>
<b>destList</b>
</field>
深度映射(Deep Mapping)
所谓深度映射,是指允许你指定属性的属性(比如一个类的属性本身也是一个类)。举例来说
Source.java
public class Source {
private long id;
private String info;
}
Dest.java
public class Dest {
private long id;
private Info info;
}
public class Info {
private String content;
}
映射规则
<mapping>
<class-a>org.zp.notes.spring.common.dozer.vo.Source</class-a>
<class-b>org.zp.notes.spring.common.dozer.vo.Dest</class-b>
<field>
<a>info</a>
<b>info.content</b>
</field>
</mapping>
排除属性(Excluding Fields)
就像任何团体都有捣乱分子,类之间转换时也有想要排除的因子。
如何在做类型转换时,自动排除一些属性,Dozer提供了几种方法,这里只介绍一种比较通用的方法。
更多详情参考官网。
field-exclude可以排除不需要映射的属性。
<field-exclude>
<a>fieldToExclude</a>
<b>fieldToExclude</b>
</field-exclude>
单向映射(One-Way Mapping)
注:本文的映射方式,无特殊说明,都是双向映射的。
有的场景可能希望转换过程不可逆,即单向转换。
单向转换可以通过使用one-way
来开启
类级别
<mapping type="one-way">
<class-a>org.dozer.vo.TestObjectFoo</class-a>
<class-b>org.dozer.vo.TestObjectFooPrime</class-b>
<field>
<a>oneFoo</a>
<b>oneFooPrime</b>
</field>
</mapping>
属性级别
<mapping>
<class-a>org.dozer.vo.TestObjectFoo2</class-a>
<class-b>org.dozer.vo.TestObjectFooPrime2</class-b>
<field type="one-way">
<a>oneFoo2</a>
<b>oneFooPrime2</b>
</field>
<field type="one-way">
<a>oneFoo3.prime</a>
<b>oneFooPrime3</b>
</field>
全局配置(Global Configuration)
全局配置用来设置全局的配置信息。此外,任何定制转换都是在这里定义的。
全局配置都是可选的。
-
<date-format>
表示日期格式 -
<stop-on-errors>
错误处理开关 -
<wildcard>
通配符 -
<trim-strings>
裁剪字符串开关
<configuration >
<date-format>MM/dd/yyyy HH:mm</date-format>
<stop-on-errors>true</stop-on-errors>
<wildcard>true</wildcard>
<trim-strings>false</trim-strings>
<custom-converters> <!-- these are always bi-directional -->
<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>
</configuration>
全局配置的作用是帮助你少配置一些参数,如果个别类的映射规则需要变更,你可以mapping中覆盖它。
覆盖的范例如下
<mapping date-format="MM-dd-yyyy HH:mm:ss">
<!-- 省略 -->
</mapping>
<mapping wildcard="false">
<!-- 省略 -->
</mapping>
<mapping stop-on-errors="false">
<!-- 省略 -->
</mapping>
<mapping trim-strings="true">
<!-- 省略 -->
</mapping>
定制转换(Custom Converters)
如果Dozer默认的转换规则不能满足实际需要,你可以选择定制转换。
定制转换通过配置XML来告诉Dozer如何去转换两个指定的类。当Dozer转换这两个指定类的时候,会调用你的映射规则去替换标准映射规则。
为了让Dozer识别,你必须实现org.dozer.CustomConverter
接口。否则,Dozer会抛异常。
具体做法:
(1) 创建一个类实现org.dozer.CustomConverter
接口。
public class TestCustomConverter implements CustomConverter {
public Object convert(Object destination, Object source,
Class destClass, Class sourceClass) {
if (source == null) {
return null;
}
CustomDoubleObject dest = null;
if (source instanceof Double) {
// check to see if the object already exists
if (destination == null) {
dest = new CustomDoubleObject();
} else {
dest = (CustomDoubleObject) destination;
}
dest.setTheDouble(((Double) source).doubleValue());
return dest;
} else if (source instanceof CustomDoubleObject) {
double sourceObj =
((CustomDoubleObject) source).getTheDouble();
return new Double(sourceObj);
} else {
throw new MappingException("Converter TestCustomConverter "
+ "used incorrectly. Arguments passed in were:"
+ destination + " and " + source);
}
}
(2) 在xml中引用定制的映射规则
引用定制的映射规则也是分级的,你可以酌情使用。
- 全局级
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozer.sourceforge.net
http://dozer.sourceforge.net/schema/beanmapping.xsd">
<configuration>
<!-- 总是双向转换的 -->
<custom-converters>
<converter type="org.dozer.converters.TestCustomConverter" >
<class-a>org.dozer.vo.CustomDoubleObject</class-a>
<class-b>java.lang.Double</class-b>
</converter>
<!-- You are responsible for mapping everything between
ClassA and ClassB -->
<converter
type="org.dozer.converters.TestCustomHashMapConverter" >
<class-a>org.dozer.vo.TestCustomConverterHashMapObject</class-a>
<class-b>org.dozer.vo.TestCustomConverterHashMapPrimeObject</class-b>
</converter>
</custom-converters>
</configuration>
</mappings>
- 属性级
<mapping>
<class-a>org.dozer.vo.SimpleObj</class-a>
<class-b>org.dozer.vo.SimpleObjPrime2</class-b>
<field custom-converter=
"org.dozer.converters.TestCustomConverter">
<a>field1</a>
<b>field1Prime</b>
</field>
</mapping>
映射的继承(Inheritance Mapping)
Dozer支持映射规则的继承机制。
属性如果有着相同的名字则不需要在xml中配置,除非使用了hint
我们来看一个例子
<mapping>
<class-a>org.dozer.vo.SuperClass</class-a>
<class-b>org.dozer.vo.SuperClassPrime</class-b>
<field>
<a>superAttribute</a>
<b>superAttr</b>
</field>
</mapping>
<mapping>
<class-a>org.dozer.vo.SubClass</class-a>
<class-b>org.dozer.vo.SubClassPrime</class-b>
<field>
<a>attribute</a>
<b>attributePrime</b>
</field>
</mapping>
<mapping>
<class-a>org.dozer.vo.SubClass2</class-a>
<class-b>org.dozer.vo.SubClassPrime2</class-b>
<field>
<a>attribute2</a>
<b>attributePrime2</b>
</field>
</mapping>
在上面的例子中SubClass、SubClass2是SuperClass的子类;
SubClassPrime和SubClassPrime2是SuperClassPrime的子类。
superAttribute和superAttr的映射规则会被子类所继承,所以不必再重复的在子类中去声明。
相关推荐
在这个总结中,我们将深入探讨 Dozer 的核心功能、使用场景以及如何在项目中有效地利用它。 首先,让我们理解什么是对象映射。对象映射是一种编程技术,用于在不同数据模型之间转换数据。例如,从数据库记录到业务...
**Dozer库详解与使用实例** Dozer是一个强大的Java Bean到Java Bean映射库,它极大地简化了对象之间的数据转换工作。与Apache的BeanUtils相比,Dozer提供了更高级别的抽象,灵活性更高,并且能够更好地处理复杂的...
### Dozer:强大的Java Bean...总结起来,Dozer是一款非常实用的Java Bean映射工具,通过丰富的配置选项和灵活的使用方式,极大地简化了数据转换的过程。无论是初学者还是经验丰富的开发者,都可以从Dozer中受益匪浅。
1. **映射编辑器**: 使用Dozer Eclipse插件,你可以通过图形界面创建和编辑映射规则。只需右键点击项目中的Dozer配置文件(如`dozer.xml`),选择`Open With -> Dozer Mapper Editor`,就可以打开可视化的映射编辑器...
总结来说,Dozer 是一个强大的对象映射库,这篇博客文章 "Dozer 使用" 会深入讲解其核心功能和用法,同时可能包含对源码的解读和实战案例,帮助开发者更好地理解和应用这个工具。而 "DozerBeanModule" 文件可能提供...
**标题与描述解析** 标题中的"dozer5.2 jar包"指的是Dozer库的5.2版本,这是一个Java库,主要用于对象之间的映射。...使用Dozer可以极大地减少手动复制对象属性的工作,使开发者能够专注于业务逻辑的实现。
**标题解析:** ...总结来说,这个压缩包为开发者提供了一个完整的Dozer 5.5.1解决方案,包括了核心库、Spring集成扩展以及依赖关系的清单,使得在Spring和OSGi环境中使用Dozer变得更加便捷和高效。
总结来说,Dozer作为一款强大的对象映射工具,提供了丰富的映射功能,简化了Java对象间的转换工作。通过灵活的配置和自定义转换器,开发者可以应对各种复杂的映射需求。然而,在选择使用Dozer时,也应考虑其可能存在...
总结来说,Dozer 5.3.2是一款功能强大的Java数据映射和校验工具,它通过灵活的映射规则、Groovy脚本支持以及内置的校验机制,大大提升了开发效率。无论是在企业级应用还是小型项目中,Dozer都能成为你得力的助手,...
总结,Spring Boot与Dozer的结合,为Java开发者提供了便捷的对象转换解决方案。通过理解并掌握这两个工具的整合,可以有效提升开发效率,使项目更加健壮和易于维护。这个示例项目“springboot-dozer-sample”为学习...
总结起来,"sandbox_dozer"项目是关于利用Dozer库进行bean映射的实践平台,它涵盖了注解、Java API和XML映射文件等多种映射方式。通过学习和应用这个项目,开发者可以提升自己在Java对象映射方面的技能,提高代码...
总结起来,Bull-Dozer-ML-Model 主要涵盖了机器学习流程的各个环节,从数据预处理到模型构建、评估和应用,体现了数据科学在预测领域的应用。Jupyter Notebook的使用则提供了一个直观且交互式的环境,便于分享和复现...
3. **自动转换工具**:手动编写转换代码可能会导致大量的重复工作,可以使用一些库(如Dozer,MapStruct等)来自动化这个过程。 4. **性能优化**:如果数据量很大,可以考虑使用流式处理或批量转换,减少内存消耗。 ...
例如,你可以使用Java的反射机制和对象映射库如Dozer或ModelMapper将Excel数据转换为Java对象,然后存储在数据库中。 在实际应用中,我们可能还会遇到性能优化的问题,因为大型Excel文件可能导致内存消耗过大。这时...
虽然BeanUtils提供了方便的功能,但在大量属性复制或性能敏感的场景下,可以考虑使用Dozer、ModelMapper等更高级的映射库,它们提供了更丰富的映射规则和更好的性能。 总结,BeanUtils工具包是Java开发中的一个利器...
在实际应用中,除了JAXB,还可以使用其他库如`DOM`, `SAX`, `StAX`等解析XML,或者使用第三方库如Apache Commons BeanUtils或Dozer进行Bean之间的映射。这些库各有优缺点,开发者需要根据项目需求选择合适的解决方案...
请注意,以上代码没有处理嵌套的对象或集合类型,对于复杂的数据结构,你可能需要递归处理或者使用第三方库如Apache Commons BeanUtils或Dozer。 **使用示例** ```java Map, Object> map = new HashMap(); map.put...
- **性能**:Orika的映射性能优于其他类似的库,如Dozer,对于大量数据转换尤其有利。 ### 3. 使用Orika的步骤 - **添加依赖**:在项目中引入Orika的Maven或Gradle依赖。 - **创建MapperFactory**:这是Orika的...