项目经常有这样的场景,我要把对象a的name转换到对象b的name去,我们经常是使用BeanUtils.copyProperties();方法去实现的,但是这样做很大的弊端,使用反射的方式的效率慢对性能的消耗比较大, 有安全问题等等,更有的同事使用get,set方法,字段一多,这就太麻烦了。
那怎么办呢?优雅转换大师MapStruct出场MapStruct就是一个属性映射工具,与手动编写映射代码相比,MapStruct通过生成繁琐且易于出错的代码来节省时间。约定优于配置的方式,MapStruct使用合理的默认值,但在配置或实现特殊行为时不加理会。 MapStruct优点
和动态映射框架相比,MapStruct具有以下优点:
通过使用普通方法调用而不是反射来快速执行编译时类型安全性构建是清除错误报告可自定义属性映射 MapStruct使用
这里示范一下基于maven的使用方式
MapStruct代码生成器处理器选项配置1.4.1.Final org.mapstruct mapstruct-processor ${org.mapstruct.version} org.mapstruct mapstruct-jdk8 ${org.mapstruct.version} org.mapstruct mapstruct ${org.mapstruct.version} org.apache.maven.plugins maven-compiler-plugin 3.8.1 1.8 1.8 org.mapstruct mapstruct-processor ${org.mapstruct.version} org.projectlombok lombok 1.18.22 org.projectlombok lombok-mapstruct-binding 0.2.0
- mapstruct.suppressGeneratorTimesstamp
如果设置为true,将禁止在生成的映射器类中创建时间戳
默认为false
- mapstruct.suppressGeneratorVersionInfoComment
如果设置为true,将禁止在生成的映射器类中创建属性
默认为false
- mapstruct.defaultComponentModel
基于生成映射器的组件模型的名称
支持:default,cdi,spring,jsr330
默认为default,使用spring可以使用@Autowired方式注入
- mapstruct.unmappedTargetPolicy
在未使用source值填充映射方法的target的属性的情况下要应用的默认报告策略。
支持:ERROR(映射代码生成失败),WARN(构建时引起警告),IGNORE(将被忽略)
默认为WARN
创建用户类org.apache.maven.plugins maven-compiler-plugin 3.8.1 1.8 1.8 org.mapstruct mapstruct-processor ${org.mapstruct.version} -Amapstruct.suppressGeneratorTimestamp=true -Amapstruct.suppressGeneratorVersionInfoComment=true
@Data
@ApiModel(value = "用户")
public class SysUser implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "user_id", type = IdType.INPUT)
@ApiModelProperty(value = "主键id")
private Long userId;
@ApiModelProperty(value = "用户名")
private String username;
}
创建用户VO
@Data
@ApiModel(value = "前端用户展示对象")
public class UserVO implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键")
private Long userId;
@ApiModelProperty(value = "用户名")
private String username;
}
创建一个转换接口
@Mapper
public interface SysUserMapperConvert {
SysUserMapperConvert INSTANCE = Mappers.getMapper(SysUserMapperConvert.class);
UserVO toConvertUserVo(SysUser user);
}
说明:
该@Mapper注解将使用MapStruct代码生成器创建对应的映射类
在生成的方法实现中,source类型的所有可读属性都将复制到target类型的相应属性中
当一个属性于其target实体对应的名称相同时,它将被隐式映射
生成的代码如下:
public UserVO findUserByRealName(String realName) {
SysUser sysUsers = this.getOne(Wrappers.lambdaQuery().eq(SysUser::getRealName, realName));
return SysUserMapperConvert.INSTANCE.toConvertUserVo(sysUsers);
}
通过接口方法 看自动生成的代码如下
(编译自动生成的)
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2021-12-26T17:50:36+0800",
comments = "version: 1.4.1.Final, compiler: javac, environment: Java 1.8.0_111 (Oracle Corporation)"
)
public class SysUserMapperConvertImpl implements SysUserMapperConvert {
@Override
public UserVO toConvertUserVo(SysUser user) {
if ( user == null ) {
return null;
}
UserVO userVO = new UserVO();
userVO.setUserId( user.getUserId() );
userVO.setUsername( user.getUsername() );
return userVO;
}
}
MapStruct的原理是生成和自己写的代码一样的代码,这意味着这些值是通过简单的getter/setter调用而不是反射或类似的方法从source类复制到target类的。使得MapStruct的性能会比动态框架更加优秀。 自定义属性映射
当属性在target实体中具有不同的名称时,可以通过@Mapping注释指定其名称。
@Mapping(target = "username",source = "id")
UserVO toConvertUserVo(SysUser user);
多个source参数的映射
mapstruct支持多个source对象聚合成一个target的场景
如:需要将person的中description映射到UserVO中的description
将SysUser的name映射到UserVO中的username
@Mapping(source = "person.description", target = "description")
@Mapping(source = "user.username", target = "name")
UserVO toConvertUserVo(Person person, SysUser user);
常用的一些方法方式基本上就是上面这些了,如果还需要更多的用法请到官网了解学习!MapStruct是否足够优雅呢?有任何问题欢迎评论区留言讨论!



