Java日常开发中经常涉及到各种对象的转换,如:VO、DO、DTO等,我们经常会借助工具来转换对象以减轻工作量、提升工作效率,如Apache的BeanUtils,Spring的BeanUtils、Cglib的BeanCopier、阿里的FastJson等, 本篇介绍另一个高性能的对象转换工具:MapStruct。
1、MapStruct简介 MapStruct是一个生成类型安全、高性能且无依赖的JavaBean映射代码的注解处理器。
官网: https://mapstruct.org/ github: https://github.com/mapstruct/mapstruct
2、MapStruct使用 2.1、引入依赖 1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > org.mapstruct</groupId > <artifactId > mapstruct</artifactId > <version > 1.4.2.Final</version > </dependency > <dependency > <groupId > org.mapstruct</groupId > <artifactId > mapstruct-processor</artifactId > <version > 1.4.2.Final</version > </dependency >
和lombok一起使用的话,需要注意lombok的版本,否则可能出现问题, 如编译后的实现类未进行get set处理。
1 2 3 4 5 <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > 1.18.8</version > </dependency >
使用Idea的话,开启注解处理: File->Settings->Build,Execulion,Development->Complier->Annotation Processors 勾选Enable annotation processing
2.2、定义需要转换的类 1 2 3 4 5 6 7 8 9 10 @NoArgsConstructor @AllArgsConstructor @Data public class Person { private Long id; private String name; private Integer age; private String email; private Date birthday; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @NoArgsConstructor @AllArgsConstructor @Data @ToString public class PersonDTO { private Long id; private String name; private Integer age; private String email; private Date birth; private String birthDateFormat; }
2.3、定义映射类 1 2 3 4 5 6 7 8 9 10 11 12 @Mapper public interface PersonMapper { PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class); @Mappings({ @Mapping(source = "birthday", target = "birth"), @Mapping(source = "birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"), @Mapping(target = "email", ignore = true) }) PersonDTO convert (Person person) ; }
@Mapper 只有在接口加上这个注解, MapStruct才会去实现该接口 @Mapper 里有个 componentModel 属性,主要是指定实现类的类型,一般用到两个: default:默认,可以通过 Mappers.getMapper(Class) 方式获取实例对象 spring:在接口的实现类上自动添加注解 @Component,可通过 @Autowired 方式注入 @Mapping:属性映射,若源对象属性与目标对象名字一致,会自动映射对应属性 source:源属性 target:目标属性 dateFormat:String到Date日期之间相互转换,通过SimpleDateFormat进行日期格式化 ignore: 忽略这个字段 @Mappings:配置多个@Mapping
代码编译后,我们可以在target下看到自动生成的实现类PersonMapperImpl:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class PersonMapperImpl implements PersonMapper { @Override public PersonDTO convert (Person person) { if ( person == null ) { return null ; } PersonDTO personDTO = new PersonDTO(); personDTO.setBirth( person.getBirthday() ); if ( person.getBirthday() != null ) { personDTO.setBirthDateFormat( new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" ).format( person.getBirthday() ) ); } personDTO.setId( person.getId() ); personDTO.setName( person.getName() ); return personDTO; } }
2.4、测试 1 2 3 4 5 6 7 8 public class PersonConverterTest { public static void main (String[] args) { Person person = new Person(1L , "river106" , "xxx@gmail.com" , new Date()); PersonDTO personDTO = PersonMapper.INSTANCE.convert(person); System.out.println(personDTO); } }
2.5、交由Spring管理 添加spring相关依赖:
1 2 3 4 5 <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > 5.1.5.RELEASE</version > </dependency >
新增转换类PersonMapperSpring,@Mapper注解componentModel属性改为spring;
1 2 3 4 5 6 7 8 9 10 @Mapper(componentModel = "spring") public interface PersonMapperSpring { @Mappings({ @Mapping(source = "birthday", target = "birth"), @Mapping(source = "birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"), @Mapping(target = "email", ignore = true) }) PersonDTO convert (Person person) ; }
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 @Configuration @ComponentScan(value = "cn.river.mapstruct") public class PersonConverterSpringTest { public static void main (String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PersonConverterSpringTest.class); Person person = new Person(1L , "river106" , "xxx@gmail.com" , new Date()); PersonMapperSpring bean = context.getBean(PersonMapperSpring.class); PersonDTO personDTO = bean.convert(person); System.out.println(personDTO); } }
3、和其他转换工具性能对比 使用如上简单对象,转换1000000次结果如下(时间单位:毫秒):
fastjson :2862 springBeanUtils :495 beanCopier :122 mapstruct :16
从测试结果来看,MapStruct转换性能是最好的。