mapstruct是一个注释解释器,可用于对象与对象之间属性值的转换,如DO-》DTO
1.引入依赖
<properties>
<org.mapstruct.version>1.3.1.Final</org.mapstruct.version>
<lombok.version>1.18.12</lombok.version>
</properties>
<dependency>
<groupId>org.mapstruct</groupId>
<!-- jdk8以下就使用mapstruct -->
<artifactId>mapstruct-jdk8</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
2.映射对象
Person(DO) -》 PersonDTO (DTO), User 是 Person的一个属性
/**
* @ClassName PersonDTO
* @Description TODO
* @Author zyf
* @Date 2020/9/3 9:46
* @Version 1.0
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PersonDTO {
private Long id;
private String name;
private String email;
/**
* 与 DO 里面的字段名称(birthDay)不一致
*/
private Date birth;
/**
* 对应 Person.user.age
*/
private Integer age;
/**
* 对 DO 里面的字段(birthDay)进行拓展,dateFormat 的形式
*/
private String birthDateFormat;
/**
* 对 DO 里面的字段(birthDay)进行拓展,expression 的形式
*/
private String birthExpressionFormat;
@Override
public String toString() {
return "PersonDTO{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", birth=" + birth +
", age=" + age +
", birthDateFormat='" + birthDateFormat + '\'' +
", birthExpressionFormat='" + birthExpressionFormat + '\'' +
'}';
}
}
/**
* @ClassName Person
* @Description TODO
* @Author zyf
* @Date 2020/9/3 9:49
* @Version 1.0
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private Long id;
private String name;
private String email;
private Date birthday;
private User user;
}
/**
* @ClassName User
* @Description TODO
* @Author zyf
* @Date 2020/9/3 9:47
* @Version 1.0
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer age;
}
3. 定义映射接口
/**
* @InterfaceName PersonConverter
* @Description DO 映射 DTO 的mapper接口,此接口编译之后会自动生成一个实现类(位于target/classes中)
* 此接口使用到@Mapper注解(org.mapstruct.Mapper),
* @Mapper 注解的 componentModel 属性,componentModel 属性用于指定自动生成的接口实现类的组件类型,这个属性支持四个值:
* default: 这是默认的情况,mapstruct 不使用任何组件类型, 可以通过Mappers.getMapper(Class)方式获取自动生成的实例对象。
* spring: 生成的实现类上面会自动添加一个@Component注解,可以通过Spring的 @Autowired方式进行注入
* cdi: the generated mapper is an application-scoped CDI bean and can be retrieved via @Inject
* jsr330: 生成的实现类上会添加@javax.inject.Named 和@Singleton注解,可以通过 @Inject注解获取
* @Author zyf
* @Date 2020/9/3 9:52
* @Version 1.0
**/
@Mapper
public interface PersonConverter {
/** 默认的方式 **/
PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);
/**
* @Author zyf
* @Description 单个 do 转 dto
* @Date 9:55 2020/9/3
* @Param
* @return
**/
@Mappings({
@Mapping(source = "birthday", target = "birth"),//不同名转换
@Mapping(source = "birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"),//不同数据类型转换
@Mapping(target = "birthExpressionFormat", expression = "java(org.apache.commons.lang3.time.DateFormatUtils.format(person.getBirthday(),\"yyyy-MM-dd HH:mm:ss\"))"),
@Mapping(source = "user.age", target = "age"),//复杂转换
@Mapping(target = "email", ignore = true)//忽略,不进行转换
})
PersonDTO domain2dto(Person person);
/**
* @Author zyf
* @Description 多个转化
* @Date 9:56 2020/9/3
* @Param
* @return
**/
List<PersonDTO> domain2dto(List<Person> persons);
}
4.编译
使用maven命令:mvn compile编译,结果发现会自动生成PersonConverter接口的实现类PersonConverterImpl,class文件内容如下:
public class PersonConverterImpl implements PersonConverter {
public PersonConverterImpl() {
}
public PersonDTO domain2dto(Person person) {
if (person == null) {
return null;
} else {
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.setAge(this.personUserAge(person));
personDTO.setId(person.getId());
personDTO.setName(person.getName());
personDTO.setBirthExpressionFormat(DateFormatUtils.format(person.getBirthday(), "yyyy-MM-dd HH:mm:ss"));
return personDTO;
}
}
public List<PersonDTO> domain2dto(List<Person> persons) {
if (persons == null) {
return null;
} else {
List<PersonDTO> list = new ArrayList(persons.size());
Iterator var3 = persons.iterator();
while(var3.hasNext()) {
Person person = (Person)var3.next();
list.add(this.domain2dto(person));
}
return list;
}
}
}
由实现类可以了解到实体类之间的转换过程,@Mapper注解起到关键作用
5.测试
@Test
public void test(){
//测试com.zyf.tuling.converter.PersonConverter的一对一映射和List集合映射
Person person = new Person(1L, "xiaozhang", "xiaozhang@163.com", new Date(), new User(11));
PersonDTO personDTO = PersonConverter.INSTANCE.domain2dto(person);
System.out.println(personDTO);
Assert.assertNotNull(personDTO);
Assert.assertEquals(personDTO.getId(), person.getId());
Assert.assertEquals(personDTO.getName(), person.getName());
Assert.assertEquals(personDTO.getBirth(), person.getBirthday());
String format = DateFormatUtils.format(personDTO.getBirth(), "yyyy-MM-dd HH:mm:ss");
Assert.assertEquals(personDTO.getBirthDateFormat(),format);
Assert.assertEquals(personDTO.getBirthExpressionFormat(),format);
List<Person> people = new ArrayList<>();
people.add(person);
List<PersonDTO> personDTOs = PersonConverter.INSTANCE.domain2dto(people);
Assert.assertNotNull(personDTOs);
}
结果如下:
PersonDTO{id=1, name='xiaozhang', email='null', birth=Tue Sep 22 20:40:05 CST 2020, age=11, birthDateFormat='2020-09-22 20:40:05', birthExpressionFormat='2020-09-22 20:40:05'}