Dozer 是一个对象转换工具。
Dozer可以在JavaBean到JavaBean之间进行递归数据复制,并且这些JavaBean可以是不同的复杂的类型。
所有的mapping,Dozer将会很直接的将名称相同的fields进行复制,如果field名不同,或者有特别的对应要求,则可以在xml中进行定义。
更多详细请参考dozer官网:http://dozer.sourceforge.net/documentation/about.html
分析多层架构的J2EE系统,经常存在JavaBean直接的拷贝。比如我们在DAO层,通过Do取得业务层需要的数据,将这些数据传递给 Service层的VO。Do与VO就存在典型的值拷贝。
典型的解决方案就是手动拷贝,弊端很明显,代码中充斥大量Set 和Get方法,真正的业务被埋藏值与值的拷贝之中。另一种方案就是使用BeanUtil,但BeanUtil不够很好的灵活性,又时候还不得不手动拷贝。Dozer可以灵活的对对象进行转换,且使用简单。
注意:Dozer支持简单类型 复杂类型的双向递归映射。
1.点击下载:http://sourceforge.net/projects/dozer/files/
2.如果使用maven工具的话,在pom.Xml文件中加入:
<dependency> <groupId>net.sf.dozer</groupId> <artifactId>dozer</artifactId> <version>5.2.1</version> </dependency> |
加入你的构建路径既可以使用。
Dozer支持
Primitive 基本数据类型 , 后面带 Wrapper 是包装类 Complex Type 是复杂类型
· Primitive to Primitive Wrapper
· 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 到复杂类型 , 如果复杂类型包含一个 String 类型的构造器
· String to Map
· Collection to Collection
· Collection to Array
· Map to Complex Type
· Map to Custom Map Type
· 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
· String to any of the supported Date/Calendar Objects.
· Objects containing a toString() method that produces a long representing time in (ms) to any supported Date/Calendar object.
根据有无映射文件和文件的多少,有三种方式:
第一种:该方式用于数据类型为基本类型,名称相同的对象映射 Mapper mapper = new DozerBeanMapper(); SourceObject sourceObject = new SourceObject(); DestinationObject destObject = (DestinationObject) mapper.map(sourceObject, DestinationObject.class); // or DestinationObject destObject = new DestinationObject(); mapper.map(sourceObject, destObject); 第二种:该方式用于数据类型不一致,或者名称不相同或者有级联关系等情况下的映射,该方式可以添加多个配置文件dozerBeanMapping.xml、someOtherDozerBeanMappings.xml 等 List myMappingFiles = new ArrayList(); myMappingFiles.add("dozerBeanMapping.xml"); //myMappingFiles.add("someOtherDozerBeanMappings.xml"); DozerBeanMapper mapper = new DozerBeanMapper(); SourceObject sourceObject = new SourceObject(); mapper.setMappingFiles(myMappingFiles); DestinationObject stObject= (DestinationObject) mapper.map(sourceObject, DestinationObject.class); 第三种:该方式用于数据类型不一致,或者名称不相同或者有级联关系等情况下的映射,配置文件只有一个映射文件叫dozerBeanMapping.xml且在根目录下 Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance(); SourceObject sourceObject = new SourceObject(); DestinationObject destObject = (DestinationObject) mapper.map(sourceObject, DestinationObject.class); //or //Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance(); //DestinationObject destObject = new DestinationObject(); mapper.map(sourceObject, destObject); |
假设我们现在有一个userDo类,如下:
package ce.dozer; public class User { private int id; private String name; private String password; private Info info; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Info getInfo() { return info; } public void setInfo(Info info) { this.info = info; } } |
一个userVo类,如下:
package ce.dozer; public class UserVO { private int id; private String userName; private String password; private InfoVO info; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public InfoVO getInfo() { return info; } public void setInfo(InfoVO info) { this.info = info; } } |
一个性別枚舉类,如下:
package ce.dozer; public enum GenderType { male,//男 female//女 } |
一个infoDo类,如下:
package ce.dozer; import java.util.Date; public class Info { private int id; private Date createDate; private GenderType gender; public int getId() { return id; } public void setId(int id) { this.id = id; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public GenderType getGender() { return gender; } public void setGender(GenderType gender) { this.gender = gender; } } |
一个infoVo类,如下:
package ce.dozer; public class InfoVO { private int id; private String date; private Integer gender; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } } |
在给出的示例中我们可以看到userDo与 userVo 中的字段对应关系
userVo |
userDo |
不同 |
id(int) |
id(int) |
|
userName(String) |
name(String) |
名称不同 |
password(String) |
password(String) |
|
Info(InfoVo) |
info (Info) |
类型不同 |
再看看infoDo与 infoVo 中的字段对应关系
infoVo |
infoDo |
不同 |
id(int) |
Id(int) |
|
createDate(String) |
date(Date) |
类型不同 |
gender(Integer) |
Gender(GenderType)枚举 |
类型不同 |
综合上面的问题我们可以如下解决方式:
<mapping> <class-a>ce.dozer.User</class-a> <class-b>ce.dozer.UserVO</class-b> <field> <a>name</a> <b>userName</b> </field> </mapping> |
<mapping date-format="yyyy-MM-dd"> <class-a>ce.dozer.User</class-a> <class-b>ce.dozer.UserVO</class-b> <field> <a>info.createDate</a> <b>info.date</b> </field> </mapping> |
<configuration> <stop-on-errors>true</stop-on-errors> <date-format>yyyy-MM-dd</date-format> <wildcard>true</wildcard> <custom-converters> <converter type=" util.EnumIntConverter"> <class-a>java.lang.Enum</class-a> <class-b>java.lang.Integer</class-b> </converter> </custom-converters> </configuration> <mapping> <class-a>ce.dozer.User</class-a> <class-b>ce.dozer.UserVO</class-b> <field> <a>info.gender</a> <b>info.gender</b> </field> </mapping> |
最终的dozerBeanMapping.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> <stop-on-errors>true</stop-on-errors> <date-format>yyyy-MM-dd</date-format> <wildcard>true</wildcard> <custom-converters> <converter type=" util.EnumIntConverter"> <class-a>java.lang.Enum</class-a> <class-b>java.lang.Integer</class-b> </converter> </custom-converters> </configuration> <mapping date-format="yyyy-MM-dd"> <class-a>ce.dozer.User</class-a> <class-b>ce.dozer.UserVO</class-b> <field> <a>info.createDate</a> <b>info.date</b> </field> <field> <a>info.gender</a> <b>info.gender</b> </field> <field> <a>info.createDate</a> <b>info.date</b> </field> <field> <a>name</a> <b>userName</b> </field> </mapping> </mappings> |
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" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-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-config/dozerBeanMapping.xml</value> </list> </property> </bean> </beans> |
private Mapper mapper ; public Mapper getMapper() { return mapper; } public void setMapper(Mapper mapper) { this.mapper = mapper; } |
getMapper().map(sourceObject, DestinationObject.class) |
Dozer的转换功能很强大,我们所能想到的类型转换,它基本都可以帮助我们完成。所以如果您想对dozer了解更多更深,建议到官网仔细阅读相关文档和说明!
官网:http://dozer.sourceforge.net/documentation/mappings.html