Springboot整合Dozer实现深度复制的方法

目录
  • Dozer
  • SpringBoot整合Dozer
    • jar依赖引入
    • dozer配置xml引入
    • Dozer的JavaConfig
    • 格式化工厂
  • 使用Demo

    Dozer

    Dozer是一种Java Bean到Java Bean的映射器,递归地将数据从一个对象复制到另一个对象,它是一个强大的,通用的,灵活的,可重用的和可配置的开源映射框架。

    常用于:

    • 代码层与层之间javabean转换, 如dao层PO转前端VO
    • 分布式中, DAO层PO转DTO, DO 以及web层DTO转VO

    注意的场景:

    • 由于bean之间的深度复制, 在进行一些类似更新, 插入操作时尤其要注意最终接收到PO的一些关键字段如ID是否是真正需要的. 场景: 传入的DTO A为查出的DTO B复制后的, 这时候A里会有B的ID, 在插入A的时候很有可能造成主键冲突.

    建议:

    • 不用Dozer最好, Dozer带来的是性能开销.(这是不可能…)
    • 某些特殊操作可以用切面控制特殊字段进行置空操作

    SpringBoot整合Dozer

    jar依赖引入

    pom.xml加入以下依赖

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

    dozer配置xml引入

    resource文件夹下新建dozer文件夹, 并新建bean-mappings.xml, global-configuration.xml

    bean-mappings.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">
    </mappings>

    global-configuration.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>
            <date-format>yyyy-MM-dd HH:mm:ss</date-format>      
            <wildcard>true</wildcard>
            <trim-strings>false</trim-strings>
            <!-- 自定义的枚举与Integer转换器, 下节介绍 -->
            <custom-converters>
                <converter type="com.dongao.beacon.ds.web.admin.tookit.EnumIntegerBiDirectionalDozerConverter">
                    <class-a>java.lang.Enum</class-a>
                    <class-b>java.lang.Integer</class-b>
                </converter>
            </custom-converters>
        </configuration>
    </mappings>

    Dozer的JavaConfig

    用于SpringBoot寻找DozerBeanMapperFactoryBean的配置
    新建DozerMapperConfig.java

    public class DozerMapperConfig {
    
        @Bean
        public DozerBeanMapperFactoryBean dozerBeanMapperFactoryBean(@Value("classpath*:dozer/*.xml") Resource[] resources) throws Exception {
            final DozerBeanMapperFactoryBean dozerBeanMapperFactoryBean = new DozerBeanMapperFactoryBean();
            dozerBeanMapperFactoryBean.setMappingFiles(resources);
            return dozerBeanMapperFactoryBean;
        }
    
    }

    格式化工厂

    建议新建包专门放置Dozer工具

    接口定义: 新建IGenerator.java接口

    public interface IGenerator {
        /** 
         * @Description: 单个对象的深度复制及类型转换,vo/domain , po
         * @param s 数据对象
         * @param clz 复制目标类型
         * @return
         * @author banjuer@outlook.com
         * @Time 2018年5月9日 下午3:53:24
         */
        <T, S> T convert(S s, Class<T> clz);
        /**
         * @Description
       
        : 深度复制结果集(
        
         ResultSet
        为自定义的分页结果集)
         *
        @param s 数据对象
      
         <T, S> 
        ResultSet
       <T> convert(
       <S> s, Class<T> clz);
      /** 
         * @Description: list深度复制
         * @Time 2018年5月9日 下午3:54:08
        <T, S> List<T> convert(List<S> s, Class<T> clz);
         * @Description: set深度复制
         * @Time 2018年5月9日 下午3:54:39
        <T, S> Set<T> convert(Set<S> s, Class<T> clz);
         * @Description: 数组深度复制
         * @Time 2018年5月9日 下午3:54:57
        <T, S> T[] convert(S[] s, Class<T> clz);
    }

    IGenerator实现

    @Component
    @Lazy(true)
    public class EJBGenerator implements IGenerator {
        @Autowired
        protected Mapper dozerMapper;
        public <T, S> T convert(S s, Class<T> clz) {
            if (s == null) {
                return null;
            }
            return this.dozerMapper.map(s, clz);
        }
         public
      
        <T, S> 
       
        ResultSet
       <T> 
      convert
       (
       <S> s, Class<T> clz) {
         
      if (s == null) {
         return null
       ;
         }
        resultSet
        = 
      new
       <T>();
      for
        (S vs : s.getResult()) {
       .getResult().add(
      this
       .dozerMapper.map(vs, clz));
       .setTotal(s.getTotal());
       .setExt(s.getExt());
       .setModifyTime(s.getModifyTime());
      return
        
      public <T, S> List<T> convert(List<S> s, Class<T> clz) {
            List<T> list = new ArrayList<T>();
            for (S vs : s) {
                list.add(this.dozerMapper.map(vs, clz));
            return list;
        public <T, S> Set<T> convert(Set<S> s, Class<T> clz) {
            Set<T> set = new HashSet<T>();
                set.add(this.dozerMapper.map(vs, clz));
            return set;
        public <T, S> T[] convert(S[] s, Class<T> clz) {
            @SuppressWarnings("unchecked")
            T[] arr = (T[]) Array.newInstance(clz, s.length);
            for (int i = 0; i < s.length; i++) {
                arr[i] = this.dozerMapper.map(s[i], clz);
            return arr;
    }

    使用Demo

    一般在公共父类中引入, 此处例子为前端公共Controller引入

    @Controller
    public class BaseController  {
        @Autowired
        protected EJBGenerator ejbGenerator = new EJBGenerator();
        protected final Logger logger = LoggerFactory.getLogger(getClass());
    
    }
    // 个人信息变更记录session
    SessionUserDetails userDetails = ejbGenerator.convert(userVo, SessionUserDetails.class);

    本文转自网络,如有侵权请联系客服删除。