MapStruct GitHub 訪問地址 : https://github.com/mapstruct/mapstruct/前端
MapStrcut與其它工具對比以及使用說明! http://www.tuicool.com/articles/uiIRjaigit
在 mvc層 咱們常常會DTO對象返回給前端 進行字段渲染。咱們不喜歡將全部字段都顯示給前端,或者咱們須要修改字段返回給前端,例如 數據中存儲的上架下架是0,1 可是前端須要的字段是true 和 false。 咱們都得進行手動判斷處理而後編輯成DTO返回給前端github
MapStruct
是一種類型安全的bean
映射類生成java註釋處理器
。
咱們要作的就是定義一個映射器接口,聲明任何須需的映射方法。在編譯的過程當中,MapStruct會生成此接口的實現。該實現使用純java方法調用的源和目標對象之間的映射,MapStruct節省了時間,經過生成代碼完成繁瑣和容易出錯的代碼邏輯。。spring
<?xml version="1.0" encoding="UTF-8"?> <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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"> <properties> // ... <org.mapstruct.version>1.2.0.Final</org.mapstruct.version> </properties> <dependencies> ... <!-- MapStruct START --> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-jdk8</artifactId> <version>${org.mapstruct.version}</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${org.mapstruct.version}</version> </dependency> <!-- MapStruct END --> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${org.mapstruct.version}</version> </path> </annotationProcessorPaths> <compilerArgs> <compilerArg>-Amapstruct.defaultComponentModel=spring</compilerArg> <compilerArg>-Amapstruct.suppressGeneratorTimestamp=true</compilerArg> <compilerArg>-Amapstruct.suppressGeneratorVersionInfoComment=true</compilerArg> </compilerArgs> </configuration> </plugin> </plugins> </build> </project>
public interface BasicObjectMapper<SOURCE, TARGET> { @Mappings({}) @InheritConfiguration TARGET to(SOURCE var1); @InheritConfiguration List<TARGET> to(List<SOURCE> var1); @InheritInverseConfiguration SOURCE from(TARGET var1); @InheritInverseConfiguration List<SOURCE> from(List<TARGET> var1); }
@Data public class ProductCategory { /** 類別編碼 */ private String categoryCode; /** 類別名稱 */ private String categoryName; } @Data public class CategoryVo { private String code; private String name; } import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; @Mapper public interface CategoryMapper extends BasicObjectMapper<CategoryVo, ProductCategory> { CategoryMapper MAPPER = Mappers.getMapper(CategoryMapper.class); @Mappings({ @Mapping(source = "code", target = "categoryCode"), @Mapping(source = "name", target = "categoryName") }) ProductCategory to(CategoryVo source); } public static void main(String[] args) { CategoryMapper categoryMapper = CategoryMapper.MAPPER; CategoryVo vo = new CategoryVo(); vo.setCode("0000"); vo.setName("屬性名稱"); ProductCategory pc = categoryMapper.to(vo); // 經過 to方法獲得 ProductCategory System.out.println("1" + pc); CategoryVo vo1 = categoryMapper.from(pc); // 經過 from方法獲得 CategoryVo,既反轉 to方法 System.out.println("2" + vo1); List<ProductCategory> pcList = categoryMapper.to(Arrays.asList(vo, vo1)); // 經過to方法從集合獲得轉換後的集合 System.out.println("3" + pcList); List<CategoryVo> voList = categoryMapper.from(pcList); // 反轉集合 System.out.println("4" + voList); }
@Mapper public interface CarMapper { CarMapper MAPPER = Mappers.getMapper(CarMapper.class); @Mappings({...}) CarDto carToCarDto(Car car); default PersonDto personToPersonDto(Person person) { // hand-written mapping logic } }
@Mapper public abstract class CarMapper { @Mappings(...) public abstract CarDto carToCarDto(Car car); public PersonDto personToPersonDto(Person person) { // hand-written mapping logic } }
@Mapper public interface AddressMapper { @Mappings({ @Mapping(source = "person.description", target = "description"), @Mapping(source = "address.houseNo", target = "houseNumber") }) DeliveryAddressDto personAndAddressToDeliveryAddressDto(Person person, Address address); }
MapStruct 還提供直接引用源參數 @Mapper public interface AddressMapper { @Mappings({ @Mapping(source = "person.description", target = "description"), @Mapping(source = "hn", target = "houseNumber") }) DeliveryAddressDto personAndAddressToDeliveryAddressDto(Person person, Integer hn); }
public class Customer { private Long id; private String name; // getters and setter omitted for brevity } public class CustomerDto { public Long id; public String customerName; } @Mapper public interface CustomerMapper { CustomerMapper MAPPER = Mappers.getMapper( CustomerMapper.class ); @Mapping(source = "customerName", target = "name") Customer toCustomer(CustomerDto customerDto); @InheritInverseConfiguration CustomerDto fromCustomer(Customer customer); } // 生成的映射器以下 public class CustomerMapperImpl implements CustomerMapper { @Override public Customer toCustomer(CustomerDto customerDto) { // ... customer.setId( customerDto.id ); customer.setName( customerDto.customerName ); // ... } @Override public CustomerDto fromCustomer(Customer customer) { // ... customerDto.id = customer.getId(); customerDto.customerName = customer.getName(); // ... } }
@Mapper public interface CarMapper { CarMapper INSTANCE = Mappers.getMapper(CarMapper.class); CarDto carToCarDto(Car car); } 這種模式使客戶很是容易地使用映射器對象,而無需反覆實例化新的實例 : Car car = ...; CarDto dto = CarMapper.INSTANCE.carToCarDto( car ); 使用依賴注入 : 經過 Spring 依賴注入能夠獲取映射器對象 @Mapper(componentModel = "spring") public interface CarMapper { CarDto carToCarDto(Car car); } @Inject private CarMapper mapper;
int 到 String的轉換 @Mapper public interface CarMapper { @Mapping(source = "price", numberFormat = "$#.00") CarDto carToCarDto(Car car); @IterableMapping(numberFormat = "$#.00") List<String> prices(List<Integer> prices); } BigDecimal 轉換爲 String @Mapper public interface CarMapper { @Mapping(source = "power", numberFormat = "#.##E0") CarDto carToCarDto(Car car); } 從日期到字符串的轉換 @Mapper public interface CarMapper { @Mapping(source = "manufacturingDate", dateFormat = "dd.MM.yyyy") CarDto carToCarDto(Car car); @IterableMapping(dateFormat = "dd.MM.yyyy") List<String> stringListToDateList(List<Date> dates); } 映射對象引用 : 對象中若是包含另外一個對象的引用,此時只需爲引用的對象類型定義映射方法便可 @Mapper public interface CarMapper { CarDto carToCarDto(Car car); PersonDto personToPersonDto(Person person); } # 映射器控制嵌套的bean映射 @Mapper public interface FishTankMapper { @Mappings({ @Mapping(target = "fish.kind", source = "fish.type"), @Mapping(target = "fish.name", ignore = true), @Mapping(target = "plant", ignore = true ), @Mapping(target = "ornament", ignore = true ), @Mapping(target = "material", ignore = true), @Mapping(target = "ornament", source = "interior.ornament"), @Mapping(target = "material.materialType", source = "material"), @Mapping(target = "quality.report.organisation.name", source = "quality.report.organisationName") }) FishTankDto map( FishTank source ); }
# 手動實現的映射 public class DateMapper { public String asString(Date date) { return date != null ? new SimpleDateFormat("yyyy-MM-dd").format(date) : null; } public Date asDate(String date) { try { return date != null ? new SimpleDateFormat("yyyy-MM-dd").parse(date) : null; } catch (ParseException e) { throw new RuntimeException(e); } } } # 引用另外一個映射器類 @Mapper(uses = DateMapper.class) public class CarMapper { CarDto carToCarDto(Car car); }
@Mapper public interface CarMapper { Set<String> integerSetToStringSet(Set<Integer> integers); List<CarDto> carsToCarDtos(List<Car> cars); CarDto carToCarDto(Car car); } # 生成的集合映射方法 @Override public Set<String> integerSetToStringSet(Set<Integer> integers) { if (integers == null) { return null; } Set<String> set = new HashSet<>(); for (Integer integer : integers) { set.add(String.valueOf(integer)); } return set; } @Override public List<CarDto> carsToCarDtos(List<Car> cars) { if (cars == null) { return null; } List<CarDto> list = new ArrayList<>(); for (Car car : cars) { list.add(carToCarDto(car)); } return list; } 映射Map : public interface SourceTargetMapper { @MapMapping(valueDateFormat = "dd.MM.yyyy") Map<String, String> longDateMapToStringStringMap(Map<Long, Date> source); } 映射流 : @Mapper public interface CarMapper { Set<String> integerStreamToStringSet(Stream<Integer> integers); List<CarDto> carsToCarDtos(Stream<Car> cars); CarDto carToCarDto(Car car); }
@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); } 默認值和常量 : @Mapper(uses = StringListMapper.class) public interface SourceTargetMapper { SourceTargetMapper INSTANCE = Mappers.getMapper(SourceTargetMapper.class); @Mappings({ @Mapping(target = "stringProperty", source = "stringProp", defaultValue = "undefined"), @Mapping(target = "longProperty", source = "longProp", defaultValue = "-1"), @Mapping(target = "stringConstant", constant = "Constant Value"), @Mapping(target = "integerConstant", constant = "14"), @Mapping(target = "longWrapperConstant", constant = "3001"), @Mapping(target = "dateConstant", dateFormat = "dd-MM-yyyy", constant = "09-01-2014"), @Mapping(target = "stringListConstants", constant = "jack-jill-tom") }) Target sourceToTarget(Source s); } 表達式 : @Mapper public interface SourceTargetMapper { SourceTargetMapper INSTANCE = Mappers.getMapper(SourceTargetMapper.class); @Mapping(target = "timeAndFormat", expression = "java( new org.sample.TimeAndFormat( s.getTime(), s.getFormat() ) )") Target sourceToTarget(Source s); }
@Mapper(uses = FruitFactory.class) public interface FruitMapper { @BeanMapping(resultType = Apple.class) Fruit map(FruitDto source); } public class FruitFactory { public Apple createApple() { return new Apple("Apple"); } public Banana createBanana() { return new Banana("Banana"); } }
@MapperConfig(uses = CustomMapperViaMapperConfig.class, unmappedTargetPolicy = ReportingPolicy.ERROR) public interface CentralConfig {} @Mapper(config = CentralConfig.class, uses = { CustomMapperViaMapper.class } ) public interface SourceTargetMapper {}
本文做者:雲楊四海
原文連接:對象拷貝 - 優雅的解決方案 Mapstruct
版權歸做者全部,轉載請註明出處express