1.MapStruct快速入门使用
官网地址:http://mapstruct.org/
MapStruct是一个代码生成器,它基于约定优于配置的方法极大地简化了Java bean类型之间映射的实现。
所以映射指的就是从一个实体变化成一个实体。例如我们在实际开发中,DAO层的实体和一些数据传输对象
(DTO),大部分属性都是相同的,只有少部分的不同,通过mapStruct,可以让不同实体之间的转换变的
简单。
2.引入Maven坐标
<properties>
<org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
</properties>
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source> <!-- depending on your project -->
<target>1.8</target> <!-- depending on your project -->
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<!-- other annotation processors -->
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
3.定义两个实体
public class User {
private String userName;
private Integer age;
private String mailbox;
private String hobby;
//GET SET ...
}
public class UserDto {
private String userName;
private String age;
private String mail;
private String hobbyDto;
//GET SET ...
}
如果我们想要把User对象转换成UserDto对象,就会发现其中age类型不同,并且mailbox与mail和
hobby与hobbyDto名称不同。那么我们需要借助第三方工具或者手动编码完成,在这里我们使用
MapStruct
4.Mapper接口
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import com.example.demo.dto.UserDto;
import com.example.demo.entity.User;
@Mapper
public interface UserToUserDtoMapper {
//声明成员变量INSTANCE,从而让客户端可以访问Mapper接口的实现。
UserToUserDtoMapper INSTANCE = Mappers.getMapper( UserToUserDtoMapper.class );
@Mappings({
@Mapping(source = "mailbox",target = "mail"),
@Mapping(source = "hobby",target = "hobbyDto")
})
UserDto userToUserDto(User user);
}
1、@Mapper注解标记这个接口作为一个映射接口,并且是编译时MapStruct处理器的入口。
2、真正实现映射的方法需要源对象作为参数,并返回目标对象。映射方法的名字是随意的。对于在源
对象和目标对象中,属性名字不同的情况,可以通过@Mapping注解来配置这些名字。
3、MapStruct会自动转换不同类型,比如其中的Integer age和String age。
4、接口中会声明一个成员变量INSTANCE,从而让客户端可以访问Mapper接口的实现。
5.编译
MapStruct是以Java编译器插件的形式来处理注解,生成mapper接口的实现。因此在使用之前我们必须手
工的编译(IDE的自动编译功能不会使用到MapStruct这个插件功能)。
执行maven命令:mvn compile
可以看到在target目录来多个一个类UserToUserDtoMapperImpl.class
package com.example.demo.mapper;
import com.example.demo.dto.UserDto;
import com.example.demo.entity.User;
import javax.annotation.Generated;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2021-04-01T17:53:12+0800",
comments = "version: 1.4.1.Final, compiler: javac, environment: Java 1.8.0_265 (AdoptOpenJDK)"
)
public class UserToUserDtoMapperImpl implements UserToUserDtoMapper {
@Override
public UserDto userToUserDto(User user) {
if ( user == null ) {
return null;
}
UserDto userDto = new UserDto();
userDto.setMail( user.getMailbox() );
userDto.setHobbyDto( user.getHobby() );
userDto.setUserName( user.getUserName() );
if ( user.getAge() != null ) {
userDto.setAge( String.valueOf( user.getAge() ) );
}
return userDto;
}
}
我们发现MapStruct生成的Mapper代理类底层还是才是的原始set方法完成赋值的,并且自动处理
了类型转换。
6.测试使用
@Test
void mapStructTest() {
User user = new User();
user.setUserName("张三");
user.setAge(24);
user.setHobby("打篮球");
user.setMailbox("xxxx@test.com");
UserDto userDto = UserToUserDtoMapper.INSTANCE.userToUserDto(user);
logger.info("User转换UserDto===》"+userDto.toString());
}
输出:
User转换UserDto===》UserDto [userName=张三, age=24, mail=xxxx@test.com, hobbyDto=打
篮球]
2.@Mapper注解详解
1、@Mapper注解的componentModel属性
componentModel属性用于指定自动生成的接口实现类的组件类型。这个属性支持四个值:
default: 这是默认的情况,mapstruct不使用任何组件类型, 可以通过Mappers.getMapper(Class)
方式获取自动生成的实例对象。
cdi: the generated mapper is an application-scoped CDI bean and can be retrieved
via @Inject
spring: 生成的实现类上面会自动添加一个@Component注解,可以通过Spring的 @Autowired方式进
行注入
jsr330: 生成的实现类上会添加@javax.inject.Named 和@Singleton注解,可以通过 @Inject注解
获取。
2.我们以spring组件方式进行验证
@Mapper(componentModel = "spring")
public interface UserToUserDtoMapper {
//声明成员变量INSTANCE,从而让客户端可以访问Mapper接口的实现。
UserToUserDtoMapper INSTANCE = Mappers.getMapper( UserToUserDtoMapper.class );
@Mappings({
@Mapping(source = "mailbox",target = "mail"),
@Mapping(source = "hobby",target = "hobbyDto")
})
UserDto userToUserDto(User user);
}
3.需要注意的是,当指定组件模型为Spring的时候,我们在classpath下一定要引入spring的jar包,否则
MapStruct在编译的时候会报错。
现在再次执行"mvn compile",通过IDE反编译功能查看自动生成的Mapper实现类源码。
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2021-04-01T18:24:08+0800",
comments = "version: 1.4.1.Final, compiler: javac, environment: Java 1.8.0_265 (AdoptOpenJDK)"
)
@Component
public class UserToUserDtoMapperImpl implements UserToUserDtoMapper {
@Override
public UserDto userToUserDto(User user) {
if ( user == null ) {
return null;
}
UserDto userDto = new UserDto();
userDto.setMail( user.getMailbox() );
userDto.setHobbyDto( user.getHobby() );
userDto.setUserName( user.getUserName() );
if ( user.getAge() != null ) {
userDto.setAge( String.valueOf( user.getAge() ) );
}
return userDto;
}
}
4.测试@Autowired注入
@RunWith(SpringRunner.class)
@SpringBootTest
class SpringAopApplicationTests {
Logger logger = LoggerFactory.getLogger(SpringAopApplicationTests.class);
@Autowired
UserToUserDtoMapper userToUserDtoMapper;
@Test
void mapStructTest() {
User user = new User();
user.setUserName("张三");
user.setAge(24);
user.setHobby("打篮球");
user.setMailbox("xxxx@test.com");
UserDto userDto = userToUserDtoMapper.userToUserDto(user);
logger.info("User转换UserDto===》"+userDto.toString());
}
}
输出:
User转换UserDto===》UserDto [userName=张三, age=24, mail=xxxx@test.com, hobbyDto=打
篮球]