mapstruct 快速使用

it2024-06-29  43

mapstruct 快速使用

mapstruct 主要的作用则是用来复制对象字段使用,功能非常的强大。在没有使用 mapstruct 之前可能都在使用 BeanUtils ,但是 BeanUtils 其实问题比较多,只能处理同类型的字段并且同名称的字段,对于复杂的情况没有办法处理,其实就是 BeanUtils 使用的反射,性能较差。而 mapstruct 使用的是传统的 setter 与 getter 方式,只需要提供接口在编译的时候会生成相应的实现。

1. 添加依赖

<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-jdk8</artifactId> <version>1.3.1.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.3.1.Final</version> </dependency>

2. 简单的情况处理

下面的代码中为了缩小代码量,使用了 lombok 相关注解。

2.1 定义 User

@Data @Builder public class User { private String name; private Date createTime; }

2.2 定义 UserDto

@Data @Builder public class UserDto { private String name; private String sex; // 故意多了一个sex private String createTime; }

2.3 定义 Converter,其实就是 Mapper

此 Mapper 不是 Mybatis 的 Mapper ,是 Mapstruct 的 Mapper(org.mapstruct.Mapper)。

@Mapper public interface UserConverter { UserConverter INSTANCE = Mappers.getMapper(UserConverter.class); UserDto toUserDto(User user); }

2.4 测试一下

public class Main { public static void main(String[] args) { User user = User.builder().name("张三").createTime(new Date()).build(); UserDto userDto = UserConverter.INSTANCE.toUserDto(user); System.out.println(userVO); } }

执行后,会在 target/classes 对应的包中会产生一个 UserConverterImpl.class 内容反编译后如下:

public class UserConverterImpl implements UserConverter { public UserConverterImpl() { } public UserDto toUserDto(User user) { if (user == null) { return null; } else { UserDtoBuilder userDto = UserDto.builder(); userDto.name(user.getName()); userDto.createTime(user.getCreateTime()); return userDto.build(); } } }

3. 复杂的情况处理

复杂的情况,可能有相同字段但是不同的类型,也有可能是相同类型但是名称不同,或者是在处理的过程中需要调用一些方法进行处理等。

3.1 定义 UserComplex

@Data @Builder public class UserComplex { private String name; private Integer status; private Date createTime; }

3.2 定义 UserComplexDto

@Data @Builder public class UserComplexDto { private String userName; //在UserComplex中叫name private String status; //在UserComplex中是Integer类型 private String createTime; //在UserComplex中是Date类型 }

3.3 定义 Converter,其实就是 Mapper

@Mapper public interface UserComplexConverter { UserComplexConverter INSTANCE = Mappers.getMapper(UserComplexConverter.class); @Mappings({ @Mapping(target = "createTime",dateFormat="yyyy-MM-dd HH:mm") }) UserComplexDto toUserComplexDto1(UserComplex user); @Mappings({ @Mapping(target = "userName",source = "name"), @Mapping(target = "status",expression = "java(java.lang.String.valueOf(user.getStatus()))"), @Mapping(target = "createTime",dateFormat="yyyy-MM-dd HH:mm") }) UserComplexDto toUserComplexDto2(UserComplex user); }

3.4 测试一下

public class Main { public static void main(String[] args) { UserComplex user = UserComplex.builder().name("张三").status(10).createTime(new Date()).build(); UserComplexDto userVO = UserComplexConverter.INSTANCE.toUserComplexDto2(user); System.out.println(userVO); } }

输入内容如下:

UserComplexDto(userName=null, status=10, createTime=2020-09-18 16:14) UserComplexDto(userName=张三, status=10, createTime=2020-09-18 16:14)

在使用 toUserComplexDto1 方法处理时,因为我们指定了 @Mappings 处理不匹配的字段,这里只指定了 createTime,实际上他也给我们处理了 status。但是名称不匹配的他就不知道处理了,这也是正常的,肯定不知道如何匹配呀。

在使用 toUserComplexDto2 方法处理时,这一次通过 @Mappings 将所有的字段都明确指定了,显然都处理成功了。

注意:在使用 mapstruct 的时候,如果有类型不匹配,你没有显示的指定 @Mappings,那么会报错,如果你显示的指定了一个,其余的他也会以默认的处理方式处理。

本文由博客群发一文多发等运营工具平台 OpenWrite 发布

最新回复(0)