背景
在代码分成越来越规范的时候,就会出现这种问题,按阿里规范来说BO只是操作数据层,在我们使用mybagtis查询或者返回对象时,数据操作层都只能使用BO,而与前端交互的往往都是DTO或者Query,这里就会涉及到大量的,对象copy,一般来说对象copy大家想到的都是使用 spring提供的BeanUtils.copyProperties
或者hutool提供的,但是这些方法的实现都是基于反射,性能差而且容易出异常,很多规范严禁使用这种途径,效率最高的无疑还是传统的get、set方法类似这种
User user = new User("张三", 18);
UserDTO userDTO = new UserDTO();
userDTO.setName(user.getName);
....
这种重复无聊的代码非要影响我们的开发效率,有没有什么好的方式解决呢
这里我们就要引出我们今天的主角MapStruct,他和lombok有类似之处都是在编译器期实现的,可以等价于我们手写
使用
- 引入依赖
<properties>
<mapstruct.version>1.3.1.Final</mapstruct.version>
</properties>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
<scope>compile</scope>
</dependency>
使用起来非常简单
如我们需要做UserDTO和User的转换
我们定义一个 UserDAOMapper接口
@Mapper
public interface UserDAOMapper {
/**
* 用于转换调用,实际开发可以直接使用spirng注入
* @Mapping 用于两个实体属性不同时转换,相同可以不写
*/
UserDAOMapper INSTANCE = Mappers.getMapper( UserDAOMapper.class );
@Mapping(target = "id", source = "id")
UserDAO UserToUserDto(User user);
List<UserDAO> UsersToUserDtos(List<User> users);
}
说明:Mapper不是mybatis的mapper
测试
public class TestMapStruct {
@Test
public void test() {
//given
User user = new User();
user.setId(100l);
user.setAge(18);
user.setEmail("641884200@163.com");
User user1 = new User();
user1.setId(222l);
user1.setAge(222);
user1.setEmail("2222@163.com");
List<User> list = new ArrayList<>();
list.add(user);
list.add(user1);
UserDAO userdao = UserDAOMapper.INSTANCE.UserToUserDto(user);
List<UserDAO> userdaos = UserDAOMapper.INSTANCE.UsersToUserDtos(list);
userdaos.forEach(e -> System.out.println(e) );
System.out.println("\n" + userdao);
测试结果
原理分析
当我们的应用编译后会在编译后的目录比如 maven是 target\generated-sources\annotations 下的子目录发现生成了一个实现类 比如 我们上面的UserDAOMapper 会生成UserDAOMapperImpl 如下:
更多高级用法请参考官网
推荐博客:
https://segmentfault.com/a/1190000020663215?utm_source=tag-newest