介绍:
MapStruct Plus是MapStruct的增强工具,它基于MapStruct并实现了自动生成Mapper接口的功能,同时强化了部分功能,使得Java类型转换更加便捷、优雅。
一:MapStruct:
MapStruct是一个开源的Java库,它简化了对象到对象映射的过程。这个库是一个代码生成器,基于Java注释处理器,通过定义类转换的接口,自动实现属性转换的具体逻辑。
使用步骤:
-
添加依赖:在项目的构建文件中添加MapStruct的依赖。
-
定义映射器接口:创建一个Java接口,并使用@Mapper注解标记。在接口中定义映射方法,这些方法将自动生成实现。
-
配置映射规则:使用@Mapping注解配置源对象和目标对象之间的属性映射规则。如果属性名称相同,则会自动映射;如果名称不同,则可以通过@Mapping注解指定源属性和目标属性。
-
生成映射代码:在构建项目时,MapStruct注解处理器会自动生成映射器的实现类。
-
使用映射器:在代码中通过映射器的实例调用映射方法,将源对象转换为目标对象。
示例演示:
//定义源对象
class Student{
private Long id;
private String name;
}
//定义目标对象
class StudentBo{
private Long studentId;
private String studentName;
}
//定义映射器接口
@Mapper
public interface StudentMapper {
CarMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
@Mapping(source = "id", target = "studentId")
@Mapping(source = "name", target = "studentName")
StudentBo studentToStudentBo(Student stu);
}
//使用映射器进行对象转换
@Test
public void test{
Student stu= new Student();
stu.setId(1L);
stu.setName("Student转换StudentBo");
StudentBo stuBo= CarMapper.INSTANCE.studentToStudentBo(stu);
System.out.println(stuBo.getStudentId()); // 输出:1
System.out.println(stuBo.getStudentName()); // 输出:Student转换StudentBo
}
缺点:
- 需要定义映射器接口:虽然这有助于明确映射规则,但也增加了额外的代码量。
- 对于非常简单的映射场景,可能显得过于重量级。
二:MapStruct Plus:
MapStruct Plus则是MapStruct的扩展或增强版本,内嵌了MapStruct,并与其完全兼容。在MapStruct的基础上进行了多项增强,提供了更高级和灵活的映射功能、更好的性能和错误处理、简化的使用体验和集成以及其他实用的增强功能。如果之前已经使用MapStruct,可以无缝替换为MapStruct Plus的依赖。
功能和特点:
-
自动生成Mapper接口:用户只需在类上添加@AutoMapper注解,并指定目标类型,MapStruct Plus即可自动生成转换逻辑。
-
增强的类型转换功能:
-
支持复杂类型转换,如嵌套对象或集合的映射。
-
提供条件映射,根据某些条件决定是否执行映射,或使用不同的映射策略。
-
允许自定义转换逻辑,以处理特殊的转换需求。
-
-
性能优化:MapStruct Plus可能对映射过程进行了优化,以提高大规模数据转换的性能。
-
更好的错误处理:提供更清晰的错误消息和调试信息,帮助快速定位问题。
-
与Lombok的整合:MapStruct Plus支持与Lombok的整合,方便开发者使用。
使用步骤:
- 引入MapStruct Plus依赖:在项目的pom.xml文件中添加MapStruct Plus的依赖。
<dependency>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-spring-boot-starter</artifactId>
<version>1.3.5</version>
</dependency>
-
配置Maven插件:配置maven-compiler-plugin插件,以启用注解处理器。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
<encoding>UTF-8</encoding>
<annotationProcessorPaths>
<path>
<groupId>io.github.linpeilie</groupId>
<artifactId>mapstruct-plus-processor</artifactId>
<version>1.3.5</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>0.2.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
-
定义源对象和目标对象:
-
使用生成的Mapper接口:在需要转换对象的地方,注入Converter接口,并调用其convert方法。
示例演示:
-
定义源对象和目标对象
@Data
@AutoMapper(target = Student.class)
public class StudentBo {
private Long id;
private String name;
}
@Data
public class Student {
private Long id;
private String name;
}
- 示例代码(java代码)
@SpringBootTest
public class MapstructTest {
@Test
public void domainConvert(){
StudentBo studentBo = new StudentBo();
studentBo.setId(1l);
studentBo.setAge(20);
studentBo.setSchool(true);
studentBo.setName("StudentBo转Student");
Student convert = MapstructUtils.convert(studentBo, Student.class);
System.out.println(convert);
}
}
//输出结果:
//Student(id=1, name=StudentBo转Student, age=20, date=null, isSchool=true)
三:更多用法
1.名称不一致:
当对象之前字段名称不一致,使用 @AutoMapping(source = "", target = "")注解
@Data
@AutoMapper(target = Student.class)
public class StudentBo {
private Long id;
//目标字段不一致情况
@AutoMapping(source = "name", target = "studentName")
private String name;
}
@Data
public class Student {
private Long id;
private String studentName;
}
2. map转换对象
使用注解@AutoMapMapper
@Data
@AutoMapMapper
public class StudentBo {
private Long id;
private String name;
}
示例代码(Java代码)
@SpringBootTest
public class MapstructTest {
@Test
public void mapConvert(){
Map<String, Object> map = new HashMap<>();
map.put("id", 1l);
map.put("name", "map转StudentBo");
StudentBo convert = MapstructUtils.convert(map, StudentBo.class);
System.out.println(convert);
}
}
3.枚举转换
1.自定义枚举:
注解@AutoEnumMapper,指定需要转换字段state
@Getter
@AllArgsConstructor
@AutoEnumMapper("state")
public enum GoodsStateEnum {
ENABLED(1, "启用"),
DISABLED(0, "禁用");
private Integer state;
private String desc;
}
2.定义对象
//源对象
@Data
//转换目标对象GoodsVo
@AutoMapper(target = GoodsVo.class)
public class Goods {
//商品状态枚举
private GoodsStateEnum state;
}
//目标对象
@Data
public class GoodsVo {
private Integer state;
}
示例代码(Java代码)
@SpringBootTest
public class MapstructTest {
@Test
public void enumMapTest() {
//源对象,这里默认选择启用状态:1
Goods goods = new Goods();
goods.setState(GoodsStateEnum.ENABLED);
//转换GoodsVo对象
GoodsVo goodsVo = MapstructUtils.convert(goods, GoodsVo.class);
//结果:GoodsVo(state=1)
System.out.println(goodsVo);
}
}
(目前版本没有看到useEnums
属性,欢迎大家测试测试并留言,互相学习一下!)
当前特性从 1.2.2 开始支持(当需要进行枚举转换时(例如枚举转换为编码值,或者由编码转换为枚举),可以在目标枚举添加 @AutoEnumMapper
注解, 增加该注解后,在任意类型中需要转换该枚举时都可以自动转换。
使用该注解需要注意:当前枚举必须有一个可以保证唯一的字段,并在使用当前注解时,将该字段名,添加到注解提供的 value
属性中。枚举和使用枚举的类,要在同一个模块中。
该特性从 1.4.2 开始支持(跨模块支持,当枚举与要使用的类型,不在同一个模块(module)中时,并不能自动转换,需要指定依赖关系。在 AutoMapper
注解中,可以通过属性 useEnums
来指定,当前转换关系,需要依赖的枚举类列表。这些枚举需要被 AutoEnumMapper
注解。
需要注意的是,当两个类在同一个模块(module)中,无需指定,可以自动转换。当前特性主要解决跨模块之间不能自动转换的问题。
4.一个类与多个类之间转换
官方文档:
https://www.mapstruct.plus/introduction/about.html
综上所述,MapStruct Plus在MapStruct的基础上进行了多项增强,提供了更高级和灵活的映射功能、更好的性能和错误处理、简化的使用体验和集成以及其他实用的增强功能。这使得MapStruct Plus成为处理Java对象映射的一个强大而高效的工具。