zoukankan      html  css  js  c++  java
  • 属性复制神器-mapstruct

    我们之前说到项目中会用到各种object,vo,bo,dto等等。我们需要在不同的对象上复制属性。

    一、BeanUtils和PropertyUtils

    我们最常用的就是Common包里面的BeanUtils,或者Spring里面的BeanUtils.

    BeanUtils.copyProperties(dest, orig);
    

    还有一个PropertyUtils

    PropertyUtils.copyProperties(dest, orig);
    

    它俩区别:

    • BeanUtils和PropertyUtils复制对象时,根据属性名进行复制。

    • 如果属性名相同,但类型不同,BeanUtils会直接转换; 而PropertyUtils会直接抛出异常。

    二、自己写转换Builder

    上面的BeanUtils和PropertyUtils代码写起来很方便简洁,但是它的实现原理是基于反射,效率不是很高。如果是对服务响应要求很高的应用,用它们就不太合适。有一种方法,自己写转换关系,一个一个set。

    public class PersonBuilder {
    
        public static Person newPerson(Context context) {
            Person person = new Person();
            person.setDelRepeat(context.getDelRepeat());
            person.setSendName(context.getSendName());
            person.setSendType(context.getSendType());
            person.setInputMdnList(context.getInputMdnList());
            person.setSceneId(context.getSceneId());
            person.setGroupIdList(context.getGroupIdList());
            person.setContent(context.getContent());
            person.setImportFile(context.getImportFile());
            return person;
        }
    
        public static PersonVO newPersonVO(Context context) {
        
        ... ...
    

    这种方法没有性能问题,但是效率不高,字段少的话工作量还行,如果字段很多,会写的很头疼

    三、mapStruct

    mapStruct的原理是基于第二种方法,但是它只用写一个接口和方法,会自动生成实现类,工作量和第一种相当,效率和第二种方法一样。
     mapStruct

    1、举个官方的例子

    引入maven依赖包

    ...
    <properties>
        <org.mapstruct.version>1.4.0.Beta2</org.mapstruct.version>
    </properties>
    ...
    <dependencies>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
    </dependencies>
    

    定义Car.java

    public class Car {
     
        private String make;
        private int numberOfSeats;
        private CarType type;
     
        //constructor, getters, setters etc.
    }
    

    定义CarDto.java

    public class CarDto {
     
        private String make;
        private int seatCount;
        private String type;
     
        //constructor, getters, setters etc.
    }
    

    定义mapper

    @Mapper
    public interface CarMapper {
     
        CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); 
     
        @Mapping(source = "numberOfSeats", target = "seatCount")
        CarDto carToCarDto(Car car); 
    }
    

    使用mapper

    @Test
    public void shouldMapCarToDto() {
        //given
        Car car = new Car( "Morris", 5, CarType.SEDAN );
     
        //when
        CarDto carDto = CarMapper.INSTANCE.carToCarDto( car );
     
        //then
        assertThat( carDto ).isNotNull();
        assertThat( carDto.getMake() ).isEqualTo( "Morris" );
        assertThat( carDto.getSeatCount() ).isEqualTo( 5 );
        assertThat( carDto.getType() ).isEqualTo( "SEDAN" );
    }
    

    2、更新

    mapStruct还可以更新已有的bean

    @Mapper
    public interface CarMapper {
    
        void updateCarFromDto(CarDto carDto, @MappingTarget Car car);
    }
    

    3、支持数据类型转换

    比如int转String

    @Mapper
    public interface CarMapper {
    
        @Mapping(source = "price", numberFormat = "$#.00")
        CarDto carToCarDto(Car car);
    
        @IterableMapping(numberFormat = "$#.00")
        List<String> prices(List<Integer> prices);
    }
    

    4、支持map,set,list

    public interface SourceTargetMapper {
    
        @MapMapping(valueDateFormat = "dd.MM.yyyy")
        Map<String, String> longDateMapToStringStringMap(Map<Long, Date> source);
    }
    
    
    @Mapper
    public interface CarMapper {
    
        Set<String> integerSetToStringSet(Set<Integer> integers);
    
        List<CarDto> carsToCarDtos(List<Car> cars);
    
        CarDto carToCarDto(Car car);
    }
    

    5、支持Stream

    @Mapper
    public interface CarMapper {
    
        Set<String> integerStreamToStringSet(Stream<Integer> integers);
    
        List<CarDto> carsToCarDtos(Stream<Car> cars);
    
        CarDto carToCarDto(Car car);
    }
    

    6、自定义origin和dest的名称

    @Mapper
    public interface OrderMapper {
    
        OrderMapper INSTANCE = Mappers.getMapper( OrderMapper.class );
    
        @ValueMappings({
            @ValueMapping(source = "EXTRA", target = "SPECIAL"),
            @ValueMapping(source = "STANDARD", target = "DEFAULT"),
            @ValueMapping(source = "NORMAL", target = "DEFAULT")
        })
        ExternalOrderType orderTypeToExternalOrderType(OrderType orderType);
    }
    

    7、支持自定义的工厂模式生成bean

    用这种方式就不会new,而是用工厂的createXXX方法

    public class DtoFactory {
    
         public CarDto createCarDto() {
             return // ... custom factory logic
         }
    }
    
    public class EntityFactory {
    
         public <T extends BaseEntity> T createEntity(@TargetType Class<T> entityClass) {
             return // ... custom factory logic
         }
    }
    
    @Mapper(uses= { DtoFactory.class, EntityFactory.class } )
    public interface CarMapper {
    
        CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );
    
        CarDto carToCarDto(Car car);
    
        Car carDtoToCar(CarDto carDto);
    }
    

    8、其它

    还有其它的高级功能,自行到官网探索

     丰极
    推荐关注此文作者公众号:丰极,关注后回复“面试资料”即可获取百度阿里美团等大厂面试资料。

  • 相关阅读:
    edgeR
    R中的运算符,条件语句,控制语句
    library-type:fr-unstanded vs fisrt-stand vs second-stanrd
    R的几个基础函数
    HTseq-count
    HISAT2的运用
    shell的符号总结
    python-tuple
    python -List
    win10 ubuntu18.0 LTS双系统安装
  • 原文地址:https://www.cnblogs.com/zhangbin1989/p/13272681.html
Copyright © 2011-2022 走看看