呵呵,在《develope J2EE without EJB》中,DTO被狠很地批判了一把,rod說這完全是反模式??蓪嶋H項目當中,我們還是不得不在使用。VO,PO,一牽扯到概念總是多么復雜。。。把一個PO從頭傳到尾??從頁面到數據庫,一捅到底?NO,NO,萬一你要顯示給用戶的是幾個PO的結合怎么辦?萬一我們只是需要某幾個屬性組合在一起顯示怎么辦?一捅到底的策略是多么丑陋,而且你完全把你的數據庫設計模型暴露給用戶。所以我們需要一些map工具來轉換,在這方面,過去我只知道有個 BeanUtils,不夠靈活,而今天,接觸了下dozer,啊,跟spring一樣的理念!靈活多變,你想怎么映射,想怎么換都可以??纯此С值霓D換類型:
? 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
? 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 if an explicit date format mapping attribute is
specified.
? Objects containing a toString() method that produces a long representing time in (ms) to any
supported Date/Calendar object.
幾乎我們能想到的,它都提供了方法來做到。而且dozer可以很容易地跟spring集成。下面舉個簡單例子:
定義一個Book對象:
package com.denny_blue.dozerdemo;
public class Book {
?private String name;
?private String author;
?
?
?public Book(){
??
?}?
?public void setAuthor(String author) {
??this.author = author;
?}
?public String getAuthor() {
??return (this.author);
?}
?public void setName(String name){
??this.name=name;
?}?
?public String getName(){
??return this.name;
?}
}
簡單的,我們要實例化一個對象,然后clone此對象,注意,是clone!
package com.denny_blue.dozerdemo;
import net.sf.dozer.util.mapping.DozerBeanMapper;
import java.util.List;
import java.util.ArrayList;
public class MyFirstDozerDemo {
?public static void main(String args[]){
??Book book1=new Book();
??book1.setAuthor("dennis");
??book1.setName("dozer demo");
??DozerBeanMapper mapper=new DozerBeanMapper();
??Book book2=new Book();
??mapper.map(book1,book2);
? book2=(Book)mapper.map(book1,com.denny_blue.dozerdemo.Book.class);
??System.out.println("book2's name:"+book2.getName());
?????}
}?
OK,如此簡單,我們把book1的屬性完全復制給了book2,兩者現在是完全獨立的對象??扇绻麅H僅是這樣,我們用BeanUtils不是也很容易辦到? book2=(Book)BeanUtils.cloneBean(book1);可如果我要把book1映射給一個完全不同的類的對象怎么辦?而且他們的屬性名也不相同,怎么辦?比如,一個CookBook類:
package com.denny_blue.dozerdemo;
public class CookBook {
?private String bookName;
?private String author;
?public CookBook(){}
?public String getBookName() {
??return (this.bookName);
?}
?public void setBookName(String bookName) {
??this.bookName = bookName;
?}
?public String getAuthor() {
??return (this.author);
?}
?public void setAuthor(String author) {
??this.author = author;
?}
}
它的bookName屬性與Book的name屬性名不一樣,我們該如何復制?dozer通過xml文件的配置來靈活地達到這個目的。我們配置一個dozerBeanMapping.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mappings PUBLIC "-//DOZER//DTD MAPPINGS//EN"
"<mappings>
<configuration>
<stop-on-errors>false</stop-on-errors>
<date-format>MM/dd/yyyy HH:mm</date-format>
<wildcard>true</wildcard>
</configuration>
<mapping>
<class-a>com.denny_blue.dozerdemo.Book</class-a>
<class-b>com.denny_blue.dozerdemo.CookBook</class-b>
<field>
<a>name</a>
<b>bookName</b>
</field>
<field>
<a>author</a>
<b>author</b>
</field>
</mapping>
</mappings>
如上所示,<class-a>指定所要復制的源對象,<class-b>復制的目標對象,<a>源對象的屬性名, <b>目標對象的屬性名。wildcard默認為true,在此時默認對所有屬性進行map,如果為false,則只對在xml文件中配置的屬性進行map。此時的demo 看起來像這樣:
package com.denny_blue.dozerdemo;
import net.sf.dozer.util.mapping.DozerBeanMapper;
import java.util.List;
import java.util.ArrayList;
public class MyFirstDozerDemo {
?public static void main(String args[]){
??Book book1=new Book();
??book1.setAuthor("dennis");
??book1.setName("dozer demo");
??DozerBeanMapper mapper=new DozerBeanMapper();
? book2=(Book)mapper.map(book1,com.denny_blue.dozerdemo.Book.class);
? CookBook cookBook=new CookBook();
? List myMappingFiles = new ArrayList();
? myMappingFiles.add("dozerBeanMapping.xml");
? mapper.setMappingFiles(myMappingFiles);
? cookBook=(CookBook)mapper.map(book1,CookBook.class);
? System.out.println("cookBook's name:"+?? cookBook.getBookName()+"???? cookBook's author:"+
????????????????????? cookBook.getAuthor());
?}
}
通過mapper.setMappingFiles()設置映射文件,可以添加多個配置文件,也可以把所有的映射寫在一個配置文件里面。??更多復雜例子請見它自帶的doc。