01.Dozer框架

136 阅读2分钟

Dozer框架

1.介绍

Dozer是一个Java工具,主要用于在相同类型或不同复杂类型的JavaBean之间进行数据的递归复制

2.特点

  • 默认属性映射:如果两个JavaBean的属性名称相同,Dozer会自动将它们进行映射,而无需进行显式配置
  • 自动类型转换:Dozer可以自动处理类型不同的属性映射,只要这些类型在Dozer可理解的范围内。这可以极大地提高开发效率
  • 处理null属性:如果遇到null属性,Dozer会将对应的所有属性全部设置为null,而不会抛出NullPointerException
  • 支持多种映射方式:Dozer支持注解、API和XML三种映射方式,使得开发者可以根据具体需求选择最适合的映射方式
  • 支持复杂类型映射:Dozer不仅支持简单的属性映射,还支持复杂类型映射、双向映射、隐式显式的映射以及递归映射

3.配置

介绍

如果要映射的两个对象有完全相同的属性名,那么一切都很简单。

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

Mapper mapper = DozerBeanMapperBuilder.buildDefault();
UserDO userDO = new UserDO("sgy", "123456");
UserBO userBO = mapper.map(userDO, UserBO.class);
System.out.println(userBO);

但实际映射时,往往存在属性名不同的情况

所以,你需要一些配置来告诉Dozer应该转换什么,怎么转换

映射配置文件

介绍

在类路径下添加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">
    <!--mapping配置-->
    <mapping>
        <class-a>com.example.dozer.BeanA</class-a>
        <class-b>com.example.dozer.BeanBF</class-b>
        <field>
            <a>name</a>
            <b>relation</b>
        </field>
    </mapping>
</mappings>

4.初始化

可以自己初始化Dozer的一些配置项

Mapper mapper = DozerBeanMapperBuilder.create()
        // 映射xml文件名称
        .withMappingFiles("dozerBeanMapping.xml")
        // Bean映射设置
        .withMappingBuilder(new BeanMappingBuilder() {
            @Override
            protected void configure() {
                mapping(UserDO.class, UserBO.class)
                        //排除xxx字段
                        .exclude("xxx")
                        //为不同字段配置映射
                        .fields("userName", "username");
            }
        })
        .build();

5.工具类

/**
 * @author sgy
 * @description Dozer封装Bean属性映射
 * @date 2025/9/16
 */
public final class BeanUtil {
    private static final Mapper mapper = DozerBeanMapperBuilder.buildDefault();


    private BeanUtil() {
    }

    /**
     * 对象映射为指定类型的对象
     *
     * @param source           源对象
     * @param destinationClass 目标类型
     * @return 目标类型对象
     */
    public static <T> T map(Object source, Class<T> destinationClass) {
        if (source == null) {
            return null;
        }
        return mapper.map(source, destinationClass);
    }

    /**
     * 对象属性映射
     *
     * @param source      源对象
     * @param destination 目标对象
     */
    public static void map(Object source, Object destination) {
        if (source == null) {
            return;
        }
        mapper.map(source, destination);
    }

    public static <T> T map(Object source, Class<T> destinationClass, String mapId) {
        if (source == null) {
            return null;
        }
        return mapper.map(source, destinationClass, mapId);
    }

    public static void map(Object source, Object destination, String mapId) {
        if (source == null) {
            return;
        }
        mapper.map(source, destination, mapId);
    }

    /**
     * 将集合转成集合
     *
     * @param sourceList       源集合
     * @param destinationClass 待转类型
     */
    public static <T, E> List<T> mapList(Collection<E> sourceList, Class<T> destinationClass) {
        return mapPage(sourceList, destinationClass);
    }

    private static <T, E> List<T> mapPage(Collection<E> sourceList, Class<T> destinationClass) {
        if (sourceList == null || sourceList.isEmpty() || destinationClass == null) {
            return Collections.emptyList();
        }
        List<T> destinationList = sourceList.stream()
                .filter(Objects::nonNull)
                .map((sourceObject) -> mapper.map(sourceObject, destinationClass))
                .collect(Collectors.toList());
        return destinationList;
    }

    public static <T, E> Set<T> mapSet(Collection<E> sourceList, Class<T> destinationClass) {
        if (sourceList == null || sourceList.isEmpty() || destinationClass == null) {
            return Collections.emptySet();
        }
        return sourceList.stream().map((sourceObject) -> mapper.map(sourceObject, destinationClass)).collect(Collectors.toSet());
    }
}

6.注意

Dozer提供了整合SpringBoot的依赖,但是我不建议使用这个,因为我不建议以注入Bean的方式使用Dozer,直接把Dozer封装为工具类,以静态方法提供转换功能就可以了