后台管理系统的通用权限解决方案(四)SpringBoot整合Dozer实现对象属性复制

1 dozer介绍

dozer是Java Bean到Java Bean映射器,它以递归方式将数据从一个对象复制到另一个对象。

dozer是用来对两个对象之间属性转换的工具,有了这个工具之后,我们将一个对象的所有属性值转给另一个对象时,就不需要再去写重复的调用setget方法了。

dozer其实是对我们熟知的beanutils的封装。

2 dozer案例

  • 1)创建maven工程dozer-demo,并配置其pom.xml文件如下

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>

    <groupId>com.hsgxgroupId>
    <artifactId>dozer-demoartifactId>
    <version>1.0-SNAPSHOTversion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.2.2.RELEASEversion>
        <relativePath/>
    parent>
    <properties>
        <maven.compiler.source>8maven.compiler.source>
        <maven.compiler.target>8maven.compiler.target>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
        dependency>
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
        dependency>
        
        <dependency>
            <groupId>com.github.dozermappergroupId>
            <artifactId>dozer-spring-boot-starterartifactId>
            <version>6.5.0version>
        dependency>
    dependencies>
project>
  • 2)创建实体类UserDTOUserEntity它们的属性只有部分是一致的
package com.hsgx.pojo;

import lombok.Data;

@Data
public class UserDTO {
    private String userId;
    private String userName;
    private Integer userAge;
    private String address;
    private String birthday;
}
package com.hsgx.pojo;

import lombok.Data;

@Data
public class UserEntity {
    private String id;
    private String name;
    private Integer age;
    private String address;
    private String birthday;
}
  • 3)在resources/dozer/目录下创建dozer的全局配置文件global.dozer.xml

<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-dddate-format>
    configuration>
mappings>
  • 4)在resources/dozer/目录下创建dozer的映射文件biz.dozer.xml将不同名的属性的映射关系配置起来

<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 date-format="yyyy-MM-dd">
        <class-a>com.hsgx.pojo.UserEntityclass-a>
        <class-b>com.hsgx.pojo.UserDTOclass-b>
        <field>
            <a>ida>
            <b>userIdb>
        field>
        <field>
            <a>namea>
            <b>userNameb>
        field>
        <field>
            <a>agea>
            <b>userAgeb>
        field>
    mapping>
    
    <mapping date-format="yyyy-MM-dd" map-id="user">
        <class-a>com.hsgx.pojo.UserEntityclass-a>
        <class-b>com.hsgx.pojo.UserDTOclass-b>
        <field>
            <a>ida>
            <b>userAgeb>
        field>
        <field>
            <a>namea>
            <b>userNameb>
        field>
        <field>
            <a>agea>
            <b>userIdb>
        field>
    mapping>
mappings>

注意,这里故意将iduserAgeageuserId关联起来,只是为了验证dozer的特性。在实际开发中,要以实际需求为准。

  • 5)在resources/目录下创建application.yml配置文件
server:
  port: 8083

dozer:
  mappingFiles:
    - classpath:dozer/global.dozer.xml
    - classpath:dozer/biz.dozer.xml
  • 6)编写启动类DozerDemoApp
package com.hsgx;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DozerDemoApp {

    public static void main(String[] args) {
        SpringApplication.run(DozerDemoApp.class, args);
    }
}
  • 7)编写单元测试
package com.hsgx;

import com.github.dozermapper.core.Mapper;
import com.hsgx.pojo.UserDTO;
import com.hsgx.pojo.UserEntity;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DozerDemoApp.class)
public class DozerTest {

    @Autowired
    private Mapper mapper;

    @Test
    public void testDozer(){
        UserDTO userDTO = new UserDTO();
        userDTO.setUserId("100");
        userDTO.setUserName("hsgx");
        userDTO.setUserAge(20);
        userDTO.setAddress("gz");
        userDTO.setBirthday("2024-10-14");
        // 直接映射
        UserEntity userEntity1 = mapper.map(userDTO, UserEntity.class);
        System.out.println(userEntity1);
        // UserEntity已经初始化且个别属性已有值
        UserEntity userEntity2 = new UserEntity();
        userEntity2.setId("200");
        mapper.map(userDTO, userEntity2);
        System.out.println(userEntity2);
        // 根据 biz.dozer.xml 文件中配置的 map-id 指定映射关系
        UserEntity userEntity3 = new UserEntity();
        mapper.map(userDTO, userEntity3, "user");
        System.out.println(userEntity3);
    }
}
  • 8)执行单元测试

后台管理系统的通用权限解决方案(四)SpringBoot整合Dozer实现对象属性复制_第1张图片

可见,属性从UserDTO对象复制到了UserEntity对象,并且会覆盖UserEntity对象原来的属性。

同时,还可以根据map-id指定映射关系,如测试中UserDTO对象的id属性复制给了UserEntity对象的age属性。

需要注意的是,当前创建的UserEntityUserDTO的属性不完全一致,所以需要创建映射文件进行映射,并且还需要在application.yml中配置映射文件的位置。如果两者的属性完全一致,则不需要提供映射文件。

3 dozer工具类

为方便使用,我们可以将dozer的相关特性封装成一个工具类DozerUtils,后续项目中只需要引入该工具类,就可以直接使用。

package com.hsgx.test;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import com.github.dozermapper.core.Mapper;


/**
 * DozerUtils 工具类
 */
public class DozerUtils {
    private Mapper mapper;

    public DozerUtils(Mapper mapper) {
        this.mapper = mapper;
    }

    public Mapper getMapper() {
        return this.mapper;
    }

    /**
     * 对象属性复制
     * @param source 源对象
     * @param destinationClass 目标对象的Class类
     * @return T
     */
    public <T> T map(Object source, Class<T> destinationClass) {
        if (source == null) {
            return null;
        }
        return mapper.map(source, destinationClass);
    }

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

    /**
     * 指定 map-id 进行对象属性复制
     * @param source 源对象
     * @param destinationClass 目标对象的Class类
     * @param mapId biz.dozer.xml文件中配置的map-id
     * @return T
     */
    public <T> T map(Object source, Class<T> destinationClass, String mapId) {
        if (source == null) {
            return null;
        }
        return mapper.map(source, destinationClass, mapId);
    }

    /**
     * 指定 map-id 进行对象属性复制
     * @param source 源对象
     * @param destination 目标对象
     * @param mapId biz.dozer.xml文件中配置的map-id
     */
    public void map(Object source, Object destination, String mapId) {
        if (source == null) {
            return;
        }
        mapper.map(source, destination, mapId);
    }

    /**
     * 将List集合转成List集合
     * @param sourceList 源集合
     * @param destinationClass 待转类型
     * @return List
     */
    public <T, E> List<T> mapList(Collection<E> sourceList, Class<T> destinationClass) {
        if (sourceList == null || sourceList.isEmpty() || destinationClass == null) {
            return Collections.emptyList();
        }
        List<T> destinationList = sourceList.stream()
                .filter(item -> item != null)
                .map((sourceObject) -> mapper.map(sourceObject, destinationClass))
                .collect(Collectors.toList());
        return destinationList;
    }

    /**
     * 将Set集合转成Set集合
     * @param sourceList 源集合
     * @param destinationClass 待转类型
     * @return List
     */
    public <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());
    }
}

编写单元测试:

@Autowired
private Mapper mapper;

@Test
public void testDozer() {
    UserDTO userDTO = new UserDTO();
    userDTO.setUserId("100");
    userDTO.setUserName("hsgx");
    userDTO.setUserAge(20);
    userDTO.setAddress("gz");
    userDTO.setBirthday("2024-10-14");

    DozerUtils dozerUtils = new DozerUtils(mapper);

    // 简单对象属性复制
    UserEntity userEntity1 = dozerUtils.map(userDTO, UserEntity.class);
    System.out.println(userEntity1);

    UserEntity userEntity2 = new UserEntity();
    dozerUtils.map(userDTO, userEntity2);
    System.out.println(userEntity2);

    // 根据map-id进行对象属性复制
    UserEntity userEntity3 = dozerUtils.map(userDTO, UserEntity.class, "user");
    System.out.println(userEntity3);

    UserEntity userEntity4 = new UserEntity();
    dozerUtils.map(userDTO, userEntity4, "user");
    System.out.println(userEntity4);

    // List → List
    List<UserDTO> userDTOList = new ArrayList<>();
    userDTOList.add(userDTO);
    UserDTO userDTO2 = new UserDTO();
    userDTO2.setUserId("200");
    userDTO2.setUserName("zhangsan");
    userDTO2.setUserAge(50);
    userDTO2.setAddress("sz");
    userDTO2.setBirthday("2024-10-27");
    userDTOList.add(userDTO2);

    List<UserEntity> userEntityList = dozerUtils.mapList(userDTOList, UserEntity.class);
    System.out.println(userEntityList);

    // Set → Set
    Set<UserDTO> userDTOSet = new HashSet<>();
    userDTOSet.add(userDTO);
    userDTOSet.add(userDTO2);

    Set<UserEntity> userEntitySet = dozerUtils.mapSet(userDTOSet, UserEntity.class);
    System.out.println(userEntitySet);
}

单元测试结果:

后台管理系统的通用权限解决方案(四)SpringBoot整合Dozer实现对象属性复制_第2张图片

本节完,更多内容查阅:后台管理系统的通用权限解决方案

延伸阅读:后台管理系统的通用权限解决方案(三)SpringBoot整合Knife4j生成接口文档

你可能感兴趣的:(后台管理系统的通用权限解决方案,spring,boot,数据库,后端,Dozer,beanutils,对象属性复制)