JavaBean中對象的復制:BeanUtils和Dozer


在開發過程中,我們會遇到各種bean之間的轉換,比如用ORM框架查詢出來的數據,對應的bean,需要轉換成Dto返回給調用方,這個時候就需要進行bean的轉換了

一、org.springframework.beans.BeanUtils

BeanUtils是開發中常用到的工具類,而獲取這一工具類主要是通過導入org.springframework.beans.BeanUtils或者org.apache.commons.beanutils.BeanUtils包來獲取,但是不同的包中BeanUtils的方法使用是不一樣的,接下來就對這兩個包中的copyProperties方法進行對比。
先來看一下這兩個包中的copyProperties方法的定義:

//org.springframework.beans.BeanUtils
public static void copyProperties(Object source, Object target){....}

//org.apache.commons.beanutils.BeanUtils
public static void copyProperties(Object dest,Object orig){....}

由定義可知,在org.springframework.beans.BeanUtils包下的copyProperties第一個參數是被copy的對象,而org.apache.commons.beanutils.BeanUtils中是第二個參數,所以使用時不要弄混。

建議使用org.springframework.beans.BeanUtils包下的copyProperties,因為目標對象(target/dest)中不包含被copy的對象(source/orig)的所有字段時,apache包下的BeanUtils會報錯。

源代碼:

private static void copyProperties(Object source, Object target, @Nullable Class<?> editable, @Nullable String... ignoreProperties) throws BeansException {
        Assert.notNull(source, "Source must not be null");
        Assert.notNull(target, "Target must not be null");
        Class<?> actualEditable = target.getClass();
        if (editable != null) {
            if (!editable.isInstance(target)) {
                throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]");
            }

            actualEditable = editable;
        }

        PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
        List<String> ignoreList = ignoreProperties != null ? Arrays.asList(ignoreProperties) : null;
        PropertyDescriptor[] var7 = targetPds;
        int var8 = targetPds.length;

        for(int var9 = 0; var9 < var8; ++var9) {
            PropertyDescriptor targetPd = var7[var9];
            Method writeMethod = targetPd.getWriteMethod();
            if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
                PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
                if (sourcePd != null) {
                    Method readMethod = sourcePd.getReadMethod();
                    if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
                        try {
                            if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                                readMethod.setAccessible(true);
                            }

                            Object value = readMethod.invoke(source);  // 將源對象的key對應的值讀取出來 if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
                                writeMethod.setAccessible(true);
                            }

                            writeMethod.invoke(target, value); // 將源對象的值賦值到目標對象中
                        } catch (Throwable var15) {
                            throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", var15);
                        }
                    }
                }
            }
        }

    }

注意:復制的是屬性,而不是字段,故要加@Data注解

1、當目標對象中包含源對象的所有屬性時,會將源對象的所有屬性值都復制過來

Student類

@Data
public class Student {
    private String id;
    private String username;
    private Integer age;
}

StudentDTO

@Data
public class StudentDTO{
    private String id;
    private String username;
    private Integer age;
    private String gender;
    private Date birthday;
}

測試

public class BeanUtilsTest {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, IntrospectionException {
        Student student = new Student();
        student.setId(UUID.randomUUID().toString());
        student.setUsername("張三");
        student.setAge(22);
        StudentDTO studentDTO = new StudentDTO();
        BeanUtils.copyProperties(student,studentDTO);
        System.out.println(studentDTO);
    }
}

結果:

StudentDTO(id=4b44fd85-1f06-4395-988f-628173f13480, username=張三, age=22, gender=null, birthday=null)

 2、當目標對象不包含源對象的所有屬性時,源對象的部分屬性值會丟失

Student類

@Data
public class Student {
    private String id;
    private String username;
    private Integer age;
}

StudentDTO

@Data
public class StudentDTO{
    private String id;
    private String username;
}

測試

public class BeanUtilsTest {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, IntrospectionException {
        Student student = new Student();
        student.setId(UUID.randomUUID().toString());
        student.setUsername("張三");
        student.setAge(22);
        StudentDTO studentDTO = new StudentDTO();
        BeanUtils.copyProperties(student,studentDTO);
        System.out.println(studentDTO);
    }
}

結果:

StudentDTO(id=4fc2e73c-3ba5-448d-8884-88f3c66bbed7, username=張三)

3、當源對象和目標對象中的屬性的類型不一樣時,會報錯

Student類

@Data
public class Student {
    private String id;
    private String username;
    private Integer age;
}

StudentDTO類

@Data
public class StudentDTO extends Student{
    private String id;
    private String username;
    private Long age;
}

注意:兩個類的age屬性的類型不一樣,一個為Integer,一個為Long

測試

public class BeanUtilsTest {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, IntrospectionException {
        Student student = new Student();
        student.setId(UUID.randomUUID().toString());
        student.setUsername("張三");
        student.setAge(22);
        StudentDTO studentDTO = new StudentDTO();
        BeanUtils.copyProperties(student,studentDTO);
        System.out.println(studentDTO);
    }
}

結果

Error:(16, 18) java: com.ljxx.entity.business.StudentDTO中的getAge()無法覆蓋com.ljxx.entity.business.Student中的getAge()
  返回類型java.lang.Long與java.lang.Integer不兼容

綜上所述:BeanUtils.copyProperties只能復制對象中名稱且類型相同的屬性。對於類型不同或者名稱不同時,無法完成復制。而下面將要講述的Dozer則能很好的解決該問題。

二、Dozer

Dozer是什么?

Dozer是一個JavaBean映射工具庫。

它支持簡單的屬性映射,復雜類型映射,雙向映射,隱式顯式的映射,以及遞歸映射。

它支持三種映射方式:注解、API、XML。

Dozer的配置

為什么要有映射配置?

如果要映射的兩個對象有完全相同的屬性名,那么一切都很簡單。

只需要直接使用Dozer的API即可:

Mapper mapper = new DozerBeanMapper();
DestinationObject destObject = mapper.map(sourceObject, DestinationObject.class);

但實際映射時,往往存在屬性名不同的情況。

所以,你需要一些配置來告訴Dozer應該轉換什么,怎么轉換。

映射配置文件

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>

Dozer把對象中名稱相同的屬性進行復制,對於名稱不相同或類型不一樣,則可以在xml中進行定義。

新建一個springboot工程

1、依賴

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
        </dependency>
        <dependency>
            <groupId>com.github.dozermapper</groupId>
            <artifactId>dozer-spring-boot-starter</artifactId>
            <version>6.5.2</version>
        </dependency>
    </dependencies>

2、在application.properties中配置如下:

server.port=8002
dozer.mapping-files=classpath:dozer/dozer-config.xml

3、啟動類

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

4、如果兩個類的屬性名和類型完全一樣

注意:此時不需要進行映射,即不需要doze-config.xml文件

Student類

@Data
public class Student {
    private String id;
    private String name;
    private Integer age;
    private String birthday;
}

StudentDTO

@Data
public class StudentDTO{
    private String id;
    private String name;
    private Integer age;
    private String birthday;
}

StudentController

@RestController
public class StudentController {
    @Autowired
    private Mapper dozerMapper;
    @GetMapping("/student")
    public StudentDTO getInfo(){
        System.out.println("come");
        Student student = new Student();
        student.setId(UUID.randomUUID().toString());
        student.setName("張三");
        student.setAge(22);
        student.setBirthday("2020-06-22");
        StudentDTO studentDTO = dozerMapper.map(student,StudentDTO.class);
        System.out.println(studentDTO);
        return studentDTO;
    }
}

啟動項目后訪問http://localhost:8002/student,結果

{"id":"3a8a7daa-600a-413d-9bab-189728701a7a","name":"張三","age":22,"birthday":"2020-06-22"}

5、如果源對象和目標對象的屬性名一樣,但是類型不一樣

修改StudentDTO類

@Data
public class StudentDTO{
    private String id;
    private String name;
    private Long age;
    private Date birthday;
}

將age由Integer改為Long,將birthday由String改為Date。如果只是將Integer改為Long,由於原型包裝類和原型包裝類之間可以自動轉換,故不需要寫dozer-config.xml文件,但是String類型與Date類型不能直接轉換,故需要dozer-config.xml文件

再次訪問,報錯如下:

Caused by: java.lang.NumberFormatException: For input string: "2020-06-22"

dozer-config.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://dozermapper.github.io/schema/bean-mapping" xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping http://dozermapper.github.io/schema/bean-mapping.xsd"> <configuration> <date-format>yyyy-MM-dd</date-format> </configuration> </mappings>

啟動項目,再次訪問,結果如下:

{"id":"69a13efd-d112-4aac-8a9c-e7780bb5cb6f","name":"張三","age":22,"birthday":"2020-06-21T16:00:00.000+0000"}

發現age已經轉換成功,而birthday的樣子有點怪。我們在StudentDTO中加@JsonFormat注解

@Data
public class StudentDTO{
    private String id;
    private String name;
    private Long age;
    @JsonFormat(pattern="yyyy-MM-dd",timezone="GMT+8")
    private Date birthday;
}

啟動項目,再次訪問,結果如下:

{"id":"2d0e30a6-0f55-4629-bba4-2c2132eb7ec0","name":"張三","age":22,"birthday":"2020-06-22"}

字符串和日期映射(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>

6、如果源對象和目標對象的名稱和類型均不一樣

修改StudentDTO

@Data
public class StudentDTO{
    private String userId;
    private String userName;
    private Long userAge;
    @JsonFormat(pattern="yyyy-MM-dd",timezone="GMT+8")
    private Date userBirthday;
}

在原來的屬性名前均加上user,

修改dozer-config.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://dozermapper.github.io/schema/bean-mapping"
          xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping
                           http://dozermapper.github.io/schema/bean-mapping.xsd">

    <configuration>
        <date-format>yyyy-MM-dd</date-format>
    </configuration>
    <!--配置對象中屬性的對應關系,相同的屬性無需映射-->
    <mapping>
        <class-a>com.zwh.dozer.entity.Student</class-a>
        <class-b>com.zwh.dozer.entity.StudentDTO</class-b>
        <field>
            <a>id</a>
            <b>userId</b>
        </field>
        <field>
            <a>name</a>
            <b>username</b>
        </field>
        <field>
            <a>age</a>
            <b>userAge</b>
        </field>
        <field>
            <a>birthday</a>
            <b>userBirthday</b>
        </field>
    </mapping>

</mappings>

啟動項目,再次訪問,結果如下:

{"userId":"36662d45-47c8-47ec-ba03-84564fab30c2","username":"張三","userAge":22,"userBirthday":"2020-06-22"}

7、使用注解方式進行映射

Dozer 5.3.2版本開始支持注解方式配置映射(只有一個注解:@Mapping)。可以應對一些簡單的映射處理,復雜的就玩不轉了。

看一下@Mapping的聲明就可以知道,這個注解只能用於元素和方法。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface Mapping {
  String value() default "";
}

注意:@Mapping注解只能寫在源對象的實體類中

修改Student類

@Data
public class Student {
    @Mapping("userId")
    private String id;
    @Mapping("username")
    private String name;
    @Mapping("userAge")
    private Integer age;
    @Mapping("userBirthday")
    private String birthday;
}

現在dozer-config.xml如下

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://dozermapper.github.io/schema/bean-mapping"
          xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping
                           http://dozermapper.github.io/schema/bean-mapping.xsd">

    <configuration>
        <date-format>yyyy-MM-dd</date-format>
    </configuration>

</mappings>

啟動項目,再次訪問,結果如下:

{"userId":"4df4dde9-567c-4665-9ced-f3f70bdd5a6c","username":"張三","userAge":22,"userBirthday":"2020-06-22"}

8、配置文件使用通配符

可以發現,如果有多個類進行映射,那么dozer-config.xml文件內容會很多,當然也可分文件映射。在dozer目錄下新建user-dozer.xml,

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://dozermapper.github.io/schema/bean-mapping"
          xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping
                           http://dozermapper.github.io/schema/bean-mapping.xsd">

    <!--配置對象中屬性的對應關系,相同的屬性無需映射-->
    <mapping>
        <class-a>com.zwh.dozer.entity.Student</class-a>
        <class-b>com.zwh.dozer.entity.StudentDTO</class-b>
        <field>
            <a>id</a>
            <b>userId</b>
        </field>
        <field>
            <a>name</a>
            <b>username</b>
        </field>
        <field>
            <a>age</a>
            <b>userAge</b>
        </field>
        <field>
            <a>birthday</a>
            <b>userBirthday</b>
        </field>
    </mapping>

</mappings>

此時dozer-config.xml內容如下

<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://dozermapper.github.io/schema/bean-mapping"
          xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping
                           http://dozermapper.github.io/schema/bean-mapping.xsd">

    <configuration>
        <date-format>yyyy-MM-dd</date-format>
    </configuration>

</mappings>

配置文件

server.port=8002
dozer.mapping-files=classpath:dozer/*.xml

dozer默認不支持通配符配置,故需編寫配置類進行配置

@Configuration
public class DozerConfig {

    @Bean
    public DozerBeanMapperFactoryBean dozerMapper(@Value("${dozer.mapping-files}") Resource[] resources) throws IOException {
        DozerBeanMapperFactoryBean dozerBeanMapperFactoryBean = new DozerBeanMapperFactoryBean();
        dozerBeanMapperFactoryBean.setMappingFiles(resources);
        return dozerBeanMapperFactoryBean;
    }
}

啟動項目,結果如下:

{"userId":"e579ffcd-c5d6-4eb1-a27a-2c03e661cf81","username":"張三","userAge":22,"userBirthday":"2020-06-22"}

三、Dozer擴展

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的對象轉換。

集合和數組映射(Collection and Array Mapping)

Dozer可以自動處理以下類型的雙向轉換。

  • List to List
  • List to Array
  • Array to Array
  • Set to Set
  • Set to Array
  • Set to List

全局配置(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>      

深度映射(Deep Mapping)

所謂深度映射,是指允許你指定屬性的屬性(比如一個類的屬性本身也是一個類)。舉例來說

Source.java

public class Source {
    private long id;
    private String info;
}

Dest.java

public class Dest {
    private long id;
    private Info info;
}

Info.java

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>

定制轉換(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>  

參考文檔:https://www.cnblogs.com/aimei/p/12201238.html

 dozer官方文檔:http://dozer.sourceforge.net/documentation/gettingstarted.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM