org.mapstruct.Mapper

  • Post author:
  • Post category:其他




1.什么是Mapper?

MapStruct是一个代码生成器,它基于convention over configuration(约定优于配置)的思想,极大地简化了 Java bean 类型之间转换。



1.2 为什么使用mapstruct?

JAVA开发按照传统的MVC或DDD模型开发时,各层传输之间的bean类型不同会涉及到大量的bean转换,比如: DO、BO、DTO、entity、VO等



1.2 使用mapstruct优点 与缺点分别是什么?

*优点:

mapstruct是在编译时完成Bean转换,与内存式(BeanUtils.copy…)对比,提升了服务性能。

mapstruct是在编译时完成Bean转换, 编译后在target目录,生成对应的xxximp.java文件,代码对开发人员透明,方便定位bug。



2.项目中如何引入mapstruct

<!-- 引入pom依赖 -->
...
<properties>
	<lombok.version>1.18.16</lombok.version>
    <org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                	<!-- other annotation processors -->
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>${lombok.version}</version>
                    </path>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
...



3 mapstruct如何使用(语法说明): 直接贴代码



3.1 方式1

@Mapper 
public interface CarMapper {
    //静态成员
    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class ); 
    
    // 转换函数的定义
    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car); 2
}



3.1 方式2

//将bean交给spring管理, --> componentModel = "spring"
//目标属性未匹配时系统忽略,不打印警告日志  -->unmappedTargetPolicy = ReportingPolicy.IGNORE
// 公共的转换组件引用  --> uses = {ConvertUtil.class}
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, uses = {ConvertUtil.class}, componentModel = "spring")
public interface CarMapper {

    // 转换函数的定义
    @Mapping(source = "numberOfSeats", target = "seatCount")
    CarDto carToCarDto(Car car); 2
}



3.2 @Mapper语法小样

// 示例小样1
	@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, uses = ConvertUtil.class, componentModel = "spring")
	
	// 指定默认值
	@Mapping(target = "name", source="name", defaultValue = "我是默认值") 
	
	// 使用java可执行代码或函数
	@Mapping(target = "name", expression = "java(\"OT\" + paramBean.getId())")
	
	// 使用常量代替默认值
	@Mapping(target = "stringConstant", constant = "Constant Value")
	
	//日期格式化
	@Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
	// Integer 到 String的转换
	@Mapping(source = "price", numberFormat = "$#.00")
	//Date 转字符串
	@Mapping(source = "currentDate", dateFormat = "dd.MM.yyyy")
	

 	
 	@Mappings({
    	@Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss"),
    	@Mapping(source = "name", target = "name")
    })

	@IterableMapping(dateFormat = "dd.MM.yyyy")
	List<String> dateToString(List<Date> dates)
	
	// 引用另一个映射器类
	@Mapper(uses = PrivateDateMapper.class)
	public class CartMapper {
    	CartDto cartToCartDto(Cart cart);
	}
	public class DateMapper {
    	public String asString(Date date) {
    		...	...
    	}
    	public Date toDate(String date) {
    		...	...
    	}
	}



// 示例小样2  DO 转 DTO
	public interface PersonDo2DtoMapping {
	    PersonDo2DtoMapping INSTANCE = Mappers.getMapper(PersonDo2DtoMapping.class);
	    
	    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
	    PersonDto do2dto(PersonDo personDo);
	}

// 示例小样3  DO集合 转 DTO集合:
	public interface PersonDo2DtoMapping {
	    PersonDo2DtoMapping INSTANCE = Mappers.getMapper(PersonDo2DtoMapping.class);
	    
	    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
	    PersonDto do2dto(PersonDo personDo);
	  
	  	// 会使用domain2dto方法进行对象list转换 
	  	//   	集合的bean的转换本质是:转换的时候调用了do2dto方法,也就是说mapsstruct能自动的使用合适的转换方法
	    List<PersonDto> listToList(List<PersonDo> people);
	}

//示例小样4 多个类型的 DO 转换为一个类型的 DTO
	public interface PersonDo2DtoMapping {
	    PersonDo2DtoMapping INSTANCE = Mappers.getMapper(PersonDo2DtoMapping.class);
	    
	    @Mapping(source = "psersonDo.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
	    @Mapping(source = "userDo.name", target = "name")
	    PersonDto twoDoTOTwoDto(PersonDo personDo,UserDO userDo);
	}

//示例小样5 自定义DO 转 DTO 的映射规则
//		eg:比如的用户性别sex DO对应的是Integer类型{0:男,1:女}, DTO对应的是String类型{0:男,1:女}
	/**定义PersonSexConverterRule 转换规则类*/
	public class PersonSexConverterRule {
		public String intToString(int sex) {
	        if (sex == 0) {
	        	return "男";
	        } else {
		        return "女";
	        }
	    }
	}

	@Mapper(uses = PersonSexConverterRule.class)
	public interface PersonDo2DtoMapping {
		    PersonDo2DtoMapping INSTANCE = Mappers.getMapper(PersonDo2DtoMapping.class);
		    
		    // ?? 规则作用在哪个属性上,是根据属性类型进行规则匹配的?
		    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
		    PersonDto do2dto(PersonDo personDo);
		}

//示例小样6 spring整合:需要在映射接口的mapper注解中添加参数componentModel = "spring"
	@Mapper(uses = PersonSexConverterRule.class,componentModel = "spring")
	public interface PersonDo2DtoMapping {
		    PersonDo2DtoMapping INSTANCE = Mappers.getMapper(PersonDo2DtoMapping.class);
		    
		    // ?? 规则作用在哪个属性上,是根据属性类型进行规则匹配的?
		    @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
		    PersonDto do2dto(PersonDo personDo);
		}



版权声明:本文为zhlin110228323原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。