文章目录
前言
一、安装
二、单个对象转换
1.指定对象映射关系
2.编写测试代码
3.运行结果
4.原理解析
三、自定义实体类属性转换
1.自定义一个类型转换器
2.使用类型转换器
3.运行结果
四、工具类
总结
前言
在开发中,我们有VO、BO、POJO常见对象类型,分别服务于不同层次和常见,不同的对象类型
需要做转换,传统的方式我们使用set/get,但是一个一个手动写太繁琐和太麻烦,所以像
apache、Spring、hutool都提供了BeaenUtils工具类,那我们为什么还要使用MapStruct Plus
呢???主要是BeanUtils底层用的是反射,性能较差,而MapStruct Plus是编译期生成的,接近原
生代码效率,你就理解MapStruct Plus性能 > BeanUtils 比它厉害 牛逼就好了。MapStruct Plus是
MapStruct的PLUS版本,兼容MapStruct,额.....没学过MapStruc,不影响。
一、安装
注意:这里跟官网有点不一样,我们使用lombok,在 Maven 配置中引入 mapstruct-plus-
processor
和 lombok-mapstruct-binding
依赖是为了解决 编译期代码生成协同问题 和 Lombok
与 MapStruct 的兼容性问题。
Lombok 和 MapStruct 均依赖编译期注解处理器生成代码。若 Lombok 未先生成 getter/setter 方
法,MapStruct 将无法识别字段导致编译失败。lombok-mapstruct-binding
协调两者的处理顺序,
确保 Lombok 优先执行
从 Lombok 1.18.16 开始,必须引入该绑定库,否则 MapStruct 无法识别 Lombok 生成的构造器或
Builder 模式(如 @Builder
注解生成的类)。
<properties><mapstruct-plus.version>最新版本</mapstruct-plus.version>
</properties>
<dependencies><dependency><groupId>io.github.linpeilie</groupId><artifactId>mapstruct-plus-spring-boot-starter</artifactId><version>${mapstruct-plus.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><path><groupId>io.github.linpeilie</groupId><artifactId>mapstruct-plus-processor</artifactId><version>${mapstruct-plus.version}</version></path><path><groupId>org.projectlombok</groupId><artifactId>lombok-mapstruct-binding</artifactId><version>${mapstruct-plus.lombok.version}</version></path></annotationProcessorPaths></configuration></plugin></plugins>
</build>
二、单个对象转换
1.指定对象映射关系
在 User 或者 UserVo 上面增加注解 —— @AutoMapper,并设置 target 为对方类。
以下面代码举例,添加注解:@AutoMapper(target = UserVo.class)
User类:
@Data
@AutoMapper(target = UserVo.class)
public class User {private String username;private int age;private String password;
}
UserVo类:
@Data
@AutoMapper(target = User.class)
public class UserVo {private String username;private int age;private String password;
}
2.编写测试代码
@SpringBootTest
public class QuickStartTest {@Autowiredprivate Converter converter;@Testpublic void test(){// 创建 User 对象User user = new User();user.setUsername("wen");user.setAge(18);user.setPassword("123456");// 使用 MapStruct plus 进行对象间转换:User =》 UserVoUserVo userVo = converter.convert(user, UserVo.class);// 输出转换之后的对象System.out.println(userVo);// 测试System.out.println("user.getUsername().equals(userVo.getUsername()) = " + user.getUsername().equals(userVo.getUsername()));System.out.println("user.getAge() == userVo.getAge() = " + user.getAge() +"---" + userVo.getAge());}
}
3.运行结果
4.原理解析
User转为UserVo主要是UserVo userVo = converter.convert(user,UserVo.class);底层其实set/get实现。
@Overridepublic UserVo convert(User source) {if ( source == null ) {return null;}UserVo userVo = new UserVo();userVo.setTagList( stringToListConverter.stringToList( source.getTags() ) );userVo.setUsername( source.getUsername() );userVo.setAge( source.getAge() );return userVo;}
在target目录下的generated-source/annotations/com.taoran.mapstructplus.entity
三、自定义实体类属性转换
想起手上有一个需求,前端传身份正反面图片URL,传的是List<String>,但是数据库保存是String
并且使用,相隔保存到收据库,可以使用MapStruct Plus的自定义实体类属性转换。
有两种方式,我们讲第二种。
1、@AutoMapping expression指定表达式:适合简单。
2、自定义一个类型转换器:适合复杂。
1.自定义一个类型转换器
String转List转换器
@Component
public class StringToListConverter {public List<String> stringToList(String str) {if (str == null) {return Collections.emptyList();}return Arrays.asList(str.split(","));}
}
List转String转换器
@Component
public class ListToStringConverter {public String listToString(List<String> list) {if (list == null || list.isEmpty()) {return null;}return String.join(",", list);}
}
2.使用类型转换器
在@AutoMapper注解中使用uses指定转换器,转换器可以使用多个,并且需要在转换的属性加上
@AutoMapping注解,target指向另一个需要转化的属性。
User:
@Data
@AutoMapper(target = UserVo.class,uses = StringToListConverter.class)
public class User {private String username;private int age;private String password;@AutoMapping(target = "tagList")private String tags;
}
UserVo:
@Data
@AutoMapper(target = User.class,uses = ListToStringConverter.class)
public class UserVo {private String username;private int age;@AutoMapping(target = "tags")private List<String> tagList;
}
测试类:
@Testpublic void test1() {// 创建一个 User 对象User user = new User();user.setUsername("wen");user.setAge(18);user.setPassword("123456");user.setTags("Java,Python,C++");// 转换UserVo userVo = converter.convert(user, UserVo.class);System.out.println(userVo);}
3.运行结果
四、工具类
package com.ailian.common.core.utils;import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import io.github.linpeilie.Converter;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;import java.util.List;
import java.util.Map;/*** Mapstruct 工具类* <p>参考文档:<a href="https://mapstruct.plus/introduction/quick-start.html">mapstruct-plus</a></p>*** @author Michelle.Chung*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MapstructUtils {private final static Converter CONVERTER = SpringUtils.getBean(Converter.class);/*** 将 T 类型对象,转换为 desc 类型的对象并返回** @param source 数据来源实体* @param desc 描述对象 转换后的对象* @return desc*/public static <T, V> V convert(T source, Class<V> desc) {if (ObjectUtil.isNull(source)) {return null;}if (ObjectUtil.isNull(desc)) {return null;}return CONVERTER.convert(source, desc);}/*** 将 T 类型对象,按照配置的映射字段规则,给 desc 类型的对象赋值并返回 desc 对象** @param source 数据来源实体* @param desc 转换后的对象* @return desc*/public static <T, V> V convert(T source, V desc) {if (ObjectUtil.isNull(source)) {return null;}if (ObjectUtil.isNull(desc)) {return null;}return CONVERTER.convert(source, desc);}/*** 将 T 类型的集合,转换为 desc 类型的集合并返回** @param sourceList 数据来源实体列表* @param desc 描述对象 转换后的对象* @return desc*/public static <T, V> List<V> convert(List<T> sourceList, Class<V> desc) {if (ObjectUtil.isNull(sourceList)) {return null;}if (CollUtil.isEmpty(sourceList)) {return CollUtil.newArrayList();}return CONVERTER.convert(sourceList, desc);}/*** 将 Map 转换为 beanClass 类型的集合并返回** @param map 数据来源* @param beanClass bean类* @return bean对象*/public static <T> T convert(Map<String, Object> map, Class<T> beanClass) {if (MapUtil.isEmpty(map)) {return null;}if (ObjectUtil.isNull(beanClass)) {return null;}return CONVERTER.convert(map, beanClass);}}
总结
MapStruct Plus的用法还有很多,例如:Map转对象、类型转换、一个类与多个类之间转换、类循
环嵌套、类转换API等,具体可以看官网文档。
MapStruct Plus官网:MapStructPlus
MapStruct官网:MapStruct – Java bean mappings, the easy way!