MapStruct是一个类型安全的映射插件,能把已定义的类,映射到另一个类。解耦了对象之间的依赖关系。
一、问题场景再现
一般我们写业务时,都要处理DTO与DO的转换。假设要添加一个Man数据,将客户端传入的DTO转成DO,笨拙的做法是new一个DO将Man所有的属性赋值一遍,然后再用MyBatis的DAO插入到数据库。如下代码所示:
public class Man {//Man
private String name;
private String age;
private String mobileNO;
}
public class InsertRequst{//Man DTO
private String name;
private String age;
private String mobileNO;
private String serialNO;
private String SMSCode;
...//get set 方法省略
}
@RestController
public String insertMan(@RequestBody InsertRequst insertRequst)//客户端传入请求
{
if(!checkSMS(insertRequst.getSMSCode())){
return "验证码错误";
}
Man man=new Man(){//此处为DTO到DO的转换,其他地方需要处理Man实体,就会出现多处类似代码
name=insertRequst.name;
age=insertRequst.age;
mobileNO=insertRequst.mobileNO;
}
ManMapper.insert(man);
...//其余代码省略
}
二、MapStruct主角上场
MapStruct只适用于java 8以上版本。可以对这两个实体进行映射,需要定义一个映射器提供映射服务,这个映射器对应如下代码的ManMapper
(需要注意的是:在映射时,需要调用映射对象的set方法,所以每个需要映射的字段都必须有set方法。)
@RestController
public String insertMan(@RequestBody InsertRequst insertRequst)
{
Man man=ManMapper.INSTANCE.toMan(insertRequst);
...//其余代码省略
}
映射处理器(ManMapper 接口)
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)//这里要写上,忽略不匹配的属性
public interface ManMapper {
ManMapper INSTANCE = Mappers.getMapper( ManMapper.class );
Man toMan(InsertRequst man);
//还可以进行映射定义,假设Man的name字段是manName,如
//@Mapping(source="name",target="manName")
//Man toMan(InsertRequst man);
}
附上代码,请到git上自行下载:
https://github.com/Luolanjiao/mapstruct-demo
三、小结
最后引用MapStruct官网上的一段话,概括一下MapStruct的特点:
Compared to dynamic mapping frameworks, MapStruct offers the following advantages:
相比于上文的动态映射框架,MapStruct有如下几点优势:
Fast execution by using plain method invocations instead of reflection
使用普通的方法调用快效执行而不是编写反射
Compile-time type safety: Only objects and attributes mapping to each other can be mapped, no accidental mapping of an order entity into a customer DTO etc.
编译时类型安全:只有匹配成功的对象属性才会被成功映射,不会出现订单型实体映射到DTO
Clear error-reports at build time, if
有如下情况,运行期间会清晰报错:
. mappings are incomplete (not all target properties are mapped)
映射未全(不是所有的目标属性都能被映射到)
. mappings are incorrect (cannot find a proper mapping method or type conversion)
映射错误(找不到匹配的映射方法或类型)