<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer-spring</artifactId>
<version>5.5.1</version>
</dependency>
<dependency>
<groupId>net.sf.dozer</groupId>
<artifactId>dozer</artifactId>
<version>5.5.1</version>
</dependency>
从5.5.0版开始,Spring集成dozer包含在附加模块dozer-spring中。
将DozerBeanMapperFactoryBean添加到您的Spring配置文件中,mappingFiles属性是您应在其中指定已创建的任何自定义dozer 映射文件的位置。 如果您没有任何自定义映射,则此列表可以为空。 也可以设置自定义事件侦听器和bean工厂。
<!-- 配置dozer mapper实例 -->
<bean id="mapper" class="org.dozer.spring.DozerBeanMapperFactoryBean">
<property name="mappingFiles">
<list>
<value>classpath*:dozer-config/dozerBeanMapping.xml</value>
</list>
</property>
</bean>
之后在java文件中就可以自动注入该映射器bean
@Autowired
private Mapper dozerMapper;
重要说明:您应该将Dozer映射器bean定义为singleton =“ true”, 您应该以这种方式配置Mapper实例,这样就不必在应用程序的生命周期内为每个单独的映射重新加载和重新初始化映射文件,为每个映射重新初始化映射文件将是无效且不必要的,DozerBeanMapper类是线程安全的。
如果要避免不同功能的映射定义冲突,则可以为每个此类用例定义自己的DozerBeanMapper实例。
在开始设置自定义xml bean映射之前,让我们看一个使用Dozer的简单示例。 Dozer映射实现具有一个称为map的方法,该方法采用源对象和目标对象或目标对象类类型。 映射两个对象之后,它然后返回目标对象及其所有映射字段。
DestinationObject destObject = dozerMapper.map(sourceObject, DestinationObject.class);
或者
DestinationObject destObject = new DestinationObject();
dozerMapper.map(sourceObject, destObject);
Dozer以两种常规模式运行:隐式和显式。 隐式模式默认情况下处于激活状态,并尝试为您解析映射。 它使用简单的假设,即如果传递了两个对象进行映射,则应映射具有相同名称的bean属性。 如果还需要其他映射(无法通过命名导出),则应通过Xml,Annotations或API(三种方式)添加这些映射。
显式模式假定除非明确指定了映射,否则不应该执行或“猜测”任何映射。 在显式模式下,编码量较高,但是有时您希望完全控制映射过程中发生的事情,并且这种方法还用于许多生产性应用程序中。 隐式/显式映射开关在Dozer中称为“通配符”。 每当您在配置中遇到该问题时,您就知道从现在开始会有什么行为。
Dozer映射xml文件定义了Dozer映射引擎无法自动执行的任何自定义映射。 任何自定义的Dozer映射文件都需要注入Mapper实现中(org.dozer.DozerBeanMapper)。 支持基于setter和基于构造函数的注入。
优选地,您将使用IOC框架(例如Spring)来满足这些Dozer注入需求。 或者,可以以编程方式完成映射文件的注入。 下面是创建bean映射器的编程方法。
List myMappingFiles = new ArrayList();
myMappingFiles.add("dozerBeanMapping.xml");
myMappingFiles.add("someOtherDozerBeanMappings.xml");
dozerMapper.setMappingFiles(myMappingFiles);
DestinationObject destObject = dozerMapper.map(sourceObject, DestinationObject.class);
通过Annotations(注解)自定义映射
使用注释的明显原因是避免在映射代码中重复字段和方法名称。 可以将注释放入映射的属性本身,从而减少代码量。 但是,在某些情况下,应避免使用注释,甚至无法使用注释。 其中一些如下:
在第一种情况下,您可能会映射JAXB生成的实体或第三方DTO,并且无法放置注释。 在第二种情况下,可以选择放置大量的多行注释或使用某些重复的实体名称来隔离映射代码。 过度注释的bean可能难以阅读和理解。
重要说明:Dozer中的注释支持是试验性的,尚不涵盖复杂的用例。 但是,实现以前必须在Xml或API中实现的最简单的映射可能会很有用。
这个想法很简单。 您可以将@Mapping注释直接放在字段的getter上。 如果Dozer发现它添加了双向映射。 这意味着一次放置注释将为两种转换类型创建映射。 类型转换(例如String-Long)将被自动选择。 全局自定义转换器也可以解决。 仅当转换受通配符规则约束时,注释才起作用(默认情况下处于活动状态)。 以下示例演示了实际中的注释。
public class SourceBean {
private Long id;
private String name;
@Mapping("binaryData")
private String data;
@Mapping("pk")
public Long getId() {
return this.id;
}
public String getName() {
return this.name;
}
}
public class TargetBean {
private String pk;
private String name;
private String binaryData;
public void setPk(String pk) {
this.pk = pk;
}
public void setName(String name) {
this.name = name;
}
}
用Dozer映射给定的bean将导致所有三个字段都被映射。 属性“name”将按照命名约定进行映射。 属性“ id”将转换为“ pk”。 字段“数据”将移至“ binaryData”。 不用担心私有修饰符; 它将被自动处理。
通过XML文件自定义映射
如果要映射的两种不同类型的数据对象包含不共享公共属性名称的任何字段,则需要将类映射条目添加到自定义映射xml文件中。 这些映射xml文件在运行时由Dozer映射引擎使用。
将源字段数据复制到目标字段时,Dozer会自动执行任何类型转换。 Dozer映射引擎是双向的,因此,如果您要将目标对象映射到源对象,则无需向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">
<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>
<mapping wildcard="false">
<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>
</mappings>
一个映射元素具有多个映射元素,每个元素都有类映射声明(<class-a>)和字段级别的映射(<field>)。 默认情况下,通配符属性(wildcard)设置为true。 这意味着它将自动尝试映射两个对象中的每个属性。 当该属性设置为false时,它将仅映射显式定义的字段。
重要说明:不需要在映射xml文件中指定具有相同名称的属性。Dozer会自动将具有相同属性名称的所有字段从源对象映射到目标对象。
XML Mapping Flaws(XML映射的瑕疵)
通过API自定义映射
API映射旨在解决所有上述问题。 为了保持向后兼容性,API映射可以与现有Xml映射结合使用。 实际上,配置的某些部分(例如全局配置块)只能以Xml格式表示。
import static org.dozer.loader.api.FieldsMappingOptions.*;
import static org.dozer.loader.api.TypeMappingOptions.*;
...
BeanMappingBuilder builder = new BeanMappingBuilder() {
protected void configure() {
mapping(Bean.class, Bean.class,
TypeMappingOptions.oneWay(),
mapId("A"),
mapNull(true)
)
.exclude("excluded")
.fields("src", "dest",
copyByReference(),
collectionStrategy(true,
RelationshipType.NON_CUMULATIVE),
hintA(String.class),
hintB(Integer.class),
FieldsMappingOptions.oneWay(),
useMapId("A"),
customConverterId("id")
)
.fields("src", "dest",
customConverter("org.dozer.CustomConverter")
);
}
};
然后应将构造的构建器对象传递给DozerBeanMapper实例。 可以添加多个Builder类。
DozerBeanMapper mapper = new DozerBeanMapper();
mapper.addMapping(builder);
可以通过可选的Dozer properties文件来自定义Dozer配置属性。 默认情况下,Dozer将查找名为dozer.properties的文件以加载配置属性。 如果未找到或指定属性文件,将使用默认值。
Dozer 随着/config中的示例dozer.properties文件一起分发,该文件显示了各种选项。 只需将示例文件放在类路径中并对其进行自定义即可。
Dozer Configuration Properties
Property Name | Description | Valid Values | Default |
---|---|---|---|
dozer.statistics.enabled | Specifies whether Dozer collects runtime mapping statistics. Note that statistics gathering imposes certain performance overhead. It is not recommended to enable this option in production settings under heavy load. | true|false | false |
dozer.autoregister.jmx.beans | Specifies whether Dozer will auto register it's JMX beans with the PlatformMDBServer on startup. | true|false | true |
dozer.el.enabled | Specifies whether during Xml mappings parsing Dozer will recognize EL expressions. | true|false | false |
dozer.cache.converter.by.dest.type.maxsize | Specifies the max size for one of Dozers internal caches. | 0 - Long.MAX_VALUE | 10000 |
dozer.cache.super.type.maxsize | Specifies the max size for one of Dozers internal caches | 0 - Long.MAX_VALUE | 10000 |
org.dozer.util.DozerProxyResolver | Specifies implementation of DozerProxyResolver to be used | Valid class name | Default implementation |
org.dozer.util.DozerClassLoader | Specifies implementation of DozerClassLoader to be used | Valid class name | Default implementation |
可以选择一次将Dozer初始化信息发送到System.out,以帮助进行调试。
要启用此附加调试信息,请设置dozer.debug系统属性。
ex) -Ddozer.debug=true
将发送到System.out的信息类型包括配置文件的加载,自定义xml映射文件的加载,版本信息,类加载器信息
dozer: Trying to find Dozer configuration file: dozer.properties
dozer: Using URL [file:/local/subversion_projects/dozer/trunk/ta
rget/test-classes/dozer.properties] for Dozer global property con
figuration
dozer: Reading Dozer properties from URL [file:/local/subversion
_projects/dozer/trunk/target/test-classes/dozer.properties]
dozer: Finished configuring Dozer global properties
dozer: Initializing Dozer. Version: ${project.version}, Thread
Name:main
dozer: Dozer JMX MBean [org.dozer.jmx:type=DozerStatisticsContr
oller] auto registered with the Platform MBean Server
dozer: Dozer JMX MBean [org.dozer.jmx:type=DozerAdminController
] auto registered with the Platform MBean Server
dozer: Initializing a new instance of the dozer bean mapper.
dozer: Initializing a new instance of the dozer bean mapper.
dozer: Using the following xml files to load custom mappings fo
r the bean mapper instance: [fieldAttributeMapping.xml]
dozer: Trying to find xml mapping file: fieldAttributeMapping.x
ml
dozer: Using URL [file:/local/subversion_projects/dozer/trunk/t
arget/test-classes/fieldAttributeMapping.xml] to load custom xml
mappings
dozer: Successfully loaded custom xml mappings from URL: [file:
/local/subversion_projects/dozer/trunk/target/test-classes/field
AttributeMapping.xml]