Dozer bean mapping 示例

Dozer 是一个强大的库,它可以帮助我们避免大量不必要的代码,同时我们希望将数据从一个 bean 复制到另一个 bean。

它主要是 bean to bean mapper,它通过属性将数据从一个 java 对象递归复制到另一个 java 对象。

当我们处理深度嵌套的复杂 java bean 时,我们意识到它的全部功能,这在大型企业应用程序中很容易看到。
将数据从一个如此大的 bean 复制到另一个类似的 bean 可能需要数百行代码

7. Dozer BeanMappingBuilder 示例

到现在为止,我们学会了使用 xml 和注解配置来配置 Dozer。
现在我们将学习如何使用 BeanMappingBuilder 类以编程方式声明 Dozer 映射。

在这个例子中,我们创建了两个类 SourceObjectDestinationObject
两者都有单个字段 date,只是它们的数据类型不同。

public class DestinationObject {

	String date;
}
import java.util.Date;
public class DestinationObject {

	Date date;
}

显示推土机 BeanMappingBuilder 示例的 Java 程序。

package com.example.onitroad.dozer.api;
import org.dozer.DozerBeanMapper;
import org.dozer.loader.api.BeanMappingBuilder;
import org.dozer.loader.api.TypeMappingOptions;
public class BeanMappingBuilderExample {
	public static void main(String[] args) {
		//Bean mapping
		BeanMappingBuilder beanMappingBuilder = new BeanMappingBuilder() {
			@Override
			protected void configure() {
				String dateFormat = "MM/dd/yyyy HH:mm";
				mapping(SourceObject.class, 
						DestinationObject.class, 
						TypeMappingOptions.wildcard(true), 
						TypeMappingOptions.dateFormat(dateFormat)).
						fields("date", "date");
			}
		};
		//Example
		DozerBeanMapper dozerBeanMapper = new DozerBeanMapper();
		dozerBeanMapper.addMapping(beanMappingBuilder);
		SourceObject src = new SourceObject();
		src.setDate("08/06/2017 11:45");

		DestinationObject dest = dozerBeanMapper.map(src, DestinationObject.class);

		System.out.println("DestinationObject : " + dest);
	}
}

程序输出。

DestinationObject : DestinationObject [date=Sun Aug 06 11:45:00 IST 2017]

3. Dozer bean 映射示例

我们有两个类,ClassAClassB,具有三个字段。
字段名称相似,但它们的数据类型可能不同。
在这里,Dozer 将能够自动处理它,无需任何特殊处理。

package com.example.onitroad.dozer.simple;
public class ClassA {
	private String name;
	private String age;
	private String address;
	//Getters and Setters
}
package com.example.onitroad.dozer.simple;
public class ClassB {
	private String name;
	private int age;
	private String address;
	//Getters and Setters
}

一个简单的推土机 bean 映射示例。

package com.example.onitroad.dozer.simple;
import org.dozer.DozerBeanMapper;
public class SimpleExample 
{
	public static void main(String[] args) 
	{
		ClassA classA = new ClassA();
		classA.setAddress("Netherlands");
		classA.setName("Sajal");
		classA.setAge("50");
		ClassB classB = new DozerBeanMapper().map(classA, ClassB.class);
		System.out.println(classB);
	}
}

程序输出。

Output: ClassB toString after applying Dozer transformation : ClassB [name=Sajal, age=50, address=Netherlands]

2. Dozer maven 依赖

要使用 dozer,我们需要在 maven 项目的 pom.xml中添加以下依赖项。

<dependency>
	<groupId>net.sf.dozer</groupId>
	<artifactId>dozer</artifactId>
	<version>5.5.1</version>
</dependency>

8. Spring DozerBeanMapper 示例

如果项目中有 Spring 框架,我们可以创建已创建的 org.dozer.DozerBeanMapperbean,并将其用作下面的示例。

<?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.xsd">

	<bean id="dozerBeanMapper" class="org.dozer.DozerBeanMapper">
		<property name="mappingFiles">
			<list>
				<value>mappings/student-mapper.xml</value>
			</list>
		</property>
	</bean>

</beans>

如何使用DozerBeanMapper来映射bean。

package com.example.onitroad.dozer.demo.withspring;
import org.dozer.DozerBeanMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.example.onitroad.dozer.models.DestinationObject;
import com.example.onitroad.dozer.models.SourceObject;
import com.example.onitroad.dozer.models.Student;
public class DemoWithDozerBeanMapper {
	public static void main(String[] args) {
		SourceObject sourceObject = new SourceObject();
		sourceObject.setName("Sajal");
		sourceObject.setAddress("Netherlands");
		sourceObject.getStudents().add(new Student("S1", "C1", "diffField1"));
		sourceObject.getStudents().add(new Student("S2", "C2", "diffField2"));
		sourceObject.getStudents().add(new Student("S3", "C3", "diffField3"));
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
		DozerBeanMapper beanMapper = (DozerBeanMapper) applicationContext.getBean("dozerBeanMapper");
		DestinationObject destinationObject = beanMapper.map(sourceObject, DestinationObject.class);

		System.out.println(destinationObject);
	}
}

程序输出。

DestinationObject [name=Sajal, address=Netherlands, pupils=[
 StudentVO [name=S1, batchName=C1, homeAddress=diffField1],
 StudentVO [name=S2, batchName=C2, homeAddress=diffField2], 
 StudentVO [name=S3, batchName=C3, homeAddress=diffField3]]
]

请注意,Dozer 已成功将所有字段从 SourceObject复制到 DestinationObject类。

www. On IT Road .com

5. Dozer bean 映射注解——@Mapping

推土机配置也可以通过推土机提供的@Mapping注解来完成。
它可以放在映射属性本身上,从而减少代码量。

目前,@Mapping是 dozer 提供的唯一注释,它有助于非常简单的属性映射。
如果我们遇到任何复杂的问题,请使用 XML 映射或者自定义转换器。

在这个例子中,我修改了 XML 映射演示中使用的类,以保持方法的可比性。

package com.example.onitroad.dozer.models;
import java.util.ArrayList;
import java.util.List;
public class SourceObject {
	private String name;
	private String address;
	@Mapping("pupils")
	List<Student> students;
	//Getters and Setters
}
package com.example.onitroad.dozer.models;
public class Student {
	String name;
	@Mapping("batchName")
	String batch;
	@Mapping("homeAddress")
	String address;
	//Getters and Setters
}
package com.example.onitroad.dozer.models;
import java.util.ArrayList;
import java.util.List;
public class DestinationObject {

	private String name;
	private String address;
	List<StudentVO> pupils;
	//Getters and Setters
}
package com.example.onitroad.dozer.models;
public class StudentVO {
	String name;
	String batchName;
	String homeAddress;
	//Getters and Setters
}

Dozer @Mapping 注释示例。

import org.dozer.DozerBeanMapper;
public class AnnotationExample {
	public static void main(String[] args) 
	{
		SourceObject sourceObject = new SourceObject();
		sourceObject.setName("Sajal");
		sourceObject.setAddress("Netherlands");
		sourceObject.getStudents().add(new Student("S1", "C1", "diffField1"));
		sourceObject.getStudents().add(new Student("S2", "C2", "diffField2"));
		sourceObject.getStudents().add(new Student("S3", "C3", "diffField3"));

		DestinationObject targetObj = new DozerBeanMapper().map(sourceObject, DestinationObject.class);
		System.out.println("DestinationObject : " + targetObj);
	}
}

程序输出。

DestinationObject [name=Sajal, address=Netherlands, pupils=[
 StudentVO [name=S1, batchName=C1, homeAddress=diffField1],
 StudentVO [name=S2, batchName=C2, homeAddress=diffField2], 
 StudentVO [name=S3, batchName=C3, homeAddress=diffField3]]
]

4. Dozer bean 映射与 xml 映射

在这个例子中,SourceObject包含一个 Student对象列表和一些其他字段。
类似地,DestinationObject也有一个 StudentVO对象列表以及其他一些简单的字段。
我们将使用 XML 映射文件将 SourceObject的属性映射到 DestinationObject

package com.example.onitroad.dozer.models;
import java.util.ArrayList;
import java.util.List;
public class SourceObject {
	private String name;
	private String address;
	List<Student> students;
	//Getters and Setters
}
package com.example.onitroad.dozer.models;
public class Student {
	String name;
	String batch;
	String address;
	//Getters and Setters
}
package com.example.onitroad.dozer.models;
import java.util.ArrayList;
import java.util.List;
public class DestinationObject {

	private String name;
	private String address;
	List<StudentVO> pupils;
	//Getters and Setters
}
package com.example.onitroad.dozer.models;
public class StudentVO {
	String name;
	String batchName;
	String homeAddress;
	//Getters and Setters
}

下面给出了 Bean 映射 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>com.example.onitroad.dozer.models.SourceObject</class-a>
        <class-b>com.example.onitroad.dozer.models.DestinationObject</class-b>
        <field>
            <a>students</a>
            pupils
        </field>
    </mapping>
    <mapping>
        <class-a>com.example.onitroad.dozer.models.Student</class-a>
        <class-b>com.example.onitroad.dozer.models.StudentVO</class-b>
        <field>
            <a>batch</a>
            batchName
        </field>
        <field>
            <a>address</a>
            homeAddress
        </field>
    </mapping>
</mappings>

如需详细参考,我们可以按照推土机用户教程进行操作。

package com.example.onitroad.dozer.demo.withoutspring;
import java.util.Arrays;
import org.dozer.DozerBeanMapper;
import com.example.onitroad.dozer.models.DestinationObject;
import com.example.onitroad.dozer.models.SourceObject;
import com.example.onitroad.dozer.models.Student;
public class Demo {
	public static void main(String[] args) 
	{
		DozerBeanMapper dozerBeanMapper = new DozerBeanMapper();
		SourceObject sourceObject = new SourceObject();
		sourceObject.setName("Sajal");
		sourceObject.setAddress("Netherlands");
		sourceObject.getStudents().add(new Student("S1", "C1", "diffField1"));
		sourceObject.getStudents().add(new Student("S2", "C2", "diffField2"));
		sourceObject.getStudents().add(new Student("S3", "C3", "diffField3"));
		dozerBeanMapper.setMappingFiles(Arrays.asList("mappings\student-mapper.xml"));
		DestinationObject destinationObject = dozerBeanMapper.map(sourceObject, DestinationObject.class);
		System.out.println(destinationObject);
	}
}

程序输出。

DestinationObject [name=Sajal, address=Netherlands, pupils=[
 StudentVO [name=S1, batchName=C1, homeAddress=diffField1],
 StudentVO [name=S2, batchName=C2, homeAddress=diffField2], 
 StudentVO [name=S3, batchName=C3, homeAddress=diffField3]]
]

1. 什么是 bean mapper 及其重要性

现在,所有企业项目本质上都非常复杂,通常为了完成某些业务功能,我们需要调用外部系统、遗留组件,这些组件需要转换结构或者多或者少相同的不同类型的对象,例如域对象到外部服务请求/外部服务响应域对象等。

现在在现实世界场景中,这些请求/响应对象可能包含大量字段,因此为了将数据从一个对象复制到另一个对象,如果我们需要为此手动编写代码,则需要大量编码,例如 destination.setXYZ(source.getXYZ())本质上是重复的并且容易出错,比如缺少字段、匹配错误等。

在这些场景中,Bean mapper 出现了,并且在通过一些简单的配置和几行代码将值从一个 bean 复制到另一个 bean 时变得非常方便。
今天我们将学习Dozerbean mapper,并将在spring和non-spring方式上做演示。

6.推土机自定义转换器示例

到目前为止,我们看到了 Dozer 如何帮助我们将字段值从源对象复制到目标对象。
但是在现实生活中,我们可能需要在转换值之前和之后添加一些逻辑。
在这些情况下,推土机提供的自定义转换器开始发挥作用。
我们可以在这些转换器中添加任何类型的转换逻辑。

在此示例中,在从源复制到目标时,我们希望将字符串值转换为 UPPERCASE
让我们看看如何实现这一目标。

package com.example.onitroad.dozer.converters;
public class SourceObject {

	private String fullname;
	//Getters, Setters, Constrctors and toString Method
}
package com.example.onitroad.dozer.converters;
public class DestinationObject {

	private String fullname;
	//Getters, Setters, Constrctors and toString Method
}

任何自定义转换器都必须使用源和目标作为参数扩展“DozerConverter”。
然后我们需要覆盖 convertFrom(source, destination)convertTo(source, destination)方法来添加向前和向后转换的逻辑。

import org.apache.commons.lang3.StringUtils;
import org.dozer.DozerConverter;
public class UpperCaseConverter extends DozerConverter<String, String> 
{
	public UpperCaseConverter() {
		super(String.class, String.class);
	}
	@Override
	public String convertFrom(String source, String destination) {
		if (source != null) {
			return StringUtils.upperCase(source);
		}
		return null;
	}
	@Override
	public String convertTo(String source, String destination) {
		//No Modification when copy backward
		return convertTo(source, destination);
	}
}

现在我们需要在 Dozer 中注册这个转换器,我们将在映射文件中进行,如下所示。
这里有几个变化,比如我们可以在全局声明部分或者字段部分等中注册自定义转换器。

详情请访问推土机官方文档。

<?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>com.example.onitroad.dozer.converters.SourceObject</class-a>
        <class-b>com.example.onitroad.dozer.converters.DestinationObject</class-b>
        <field custom-converter="com.example.onitroad.dozer.converters.UpperCaseConverter" custom-converter-param="fullname">
            <a>fullname</a>
            fullname
        </field>
    </mapping>
</mappings>

现在在 spring 中注册 dozer bean 映射器,正如我们在前一节中看到的那样。

<?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.xsd">

	<bean id="dozerBeanMapper" class="org.dozer.DozerBeanMapper">
		<property name="mappingFiles">
			<list>
				<value>custom-converter-mapping.xml</value>
			</list>
		</property>
	</bean>

</beans>

推土机自定义转换器示例程序。

import org.dozer.DozerBeanMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class CustomConverterTest {
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		SourceObject sourceClassForConverters = new SourceObject("Lokesh Gupta");

		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("custom-converter-spring-beans.xml");
		DozerBeanMapper beanMapper = (DozerBeanMapper) applicationContext.getBean("dozerBeanMapper");

		DestinationObject destinationClassForConverters = beanMapper.map(sourceClassForConverters, DestinationObject.class);

		System.out.println(destinationClassForConverters);
	}
}

程序输出。

DestinationObject [fullname=LOKESH GUPTA]
日期:2020-09-17 00:10:40 来源:oir作者:oir