MapStruct GitHub 访问地址 : https://github.com/mapstruct/mapstruct/
MapStrcut与其它工具对比以及使用说明! http://www.tuicool.com/articles/uiIRjai
在 mvc层 我们经常会DTO对象返回给前端 进行字段渲染。我们不喜欢将所有字段都显示给前端,或者我们需要修改字段返回给前端,例如 数据中存储的上架下架是0,1 ?但是前端需要的字段是true 和 false。 我们都得进行手动判断处理然后编辑成DTO返回给前端
?MapStruct
是一种类型安全的bean
映射类生成java注释处理器
。
我们要做的就是定义一个映射器接口,声明任何必需的映射方法。在编译的过程中,MapStruct会生成此接口的实现。该实现使用纯java方法调用的源和目标对象之间的映射,MapStruct节省了时间,通过生成代码完成繁琐和容易出错的代码逻辑。。
<?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
版权归作者所有,转载请注明出处
原文:https://www.cnblogs.com/rolandlee/p/10946237.html