0x0 背景
项目中经常会进行对象转换,以往常使用Spring框架的BeanUtils,但是这个工具基于反射,性能较差;因此有些通过编译时生成转换类的工具出现了,例如:Selma和mapstruct等。
0x1 Selma教程
官网:http://www.selma-java.org/
maven依赖:
<!-- scope provided because the processor is only needed at compile time-->
<dependency>
<groupId>fr.xebia.extras</groupId>
<artifactId>selma-processor</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<!-- This is the only real dependency you will have in your binaries -->
<dependency>
<groupId>fr.xebia.extras</groupId>
<artifactId>selma</artifactId>
<version>1.0</version>
</dependency>
使用demo:
//定义一个pojo类User
@Data
@Accessors(chain = true)
public class User {
private Long id;
private String username;
private Integer age;
private String address;
private String email;
}
//定义对应的dto,注意,二者有个别字段不同
@Data
public class UserDto {
private Long id;
private String username;
private Integer age;
private String address;
private String nickname;
}
定义一个工具类接口
注意这里的IgnoreMissing.ALL
是指忽略转换时不一致的字段
例如user有email,而userDto没有该字段
@Mapper(withIgnoreMissing = IgnoreMissing.ALL)
public interface ConvertUtils {
ConvertUtils INSTANCE = Selma.builder(ConvertUtils.class).build();
UserDto convertToUserDto(User user);
User convertToUser(UserDto userDto);
}
接下来编译后会发现,selma帮我们生成了一个实现类,如下:
public final class ConvertUtilsSelmaGeneratedClass implements ConvertUtils {
public final UserDto convertToUserDto(User inUser) {
UserDto out = null;
if (inUser != null) {
out = new UserDto();
out.setAddress(inUser.getAddress());
out.setAge(inUser.getAge());
out.setId(inUser.getId());
out.setUsername(inUser.getUsername());
}
return out;
}
public final User convertToUser(UserDto inUserDto) {
User out = null;
if (inUserDto != null) {
out = new User();
out.setAddress(inUserDto.getAddress());
out.setAge(inUserDto.getAge());
out.setId(inUserDto.getId());
out.setUsername(inUserDto.getUsername());
}
return out;
}
public ConvertUtilsSelmaGeneratedClass() {
}
}
使用方法:
public static void main(String[] args) {
User user = new User().setUsername("AAA")
.setId(3423423L)
.setAge(23)
.setEmail("sdfsdf@qew.com")
.setAddress("asdfasdfasdfasd");
UserDto userDto = ConvertUtils.INSTANCE.convertToUserDto(user);
System.out.println(userDto);
System.out.println(ConvertUtils.INSTANCE.convertToUser(userDto));
}
对于某些字段需要转换的情况,可以使用类似如下的注解:
@Maps(withCustomFields = {
@Field({"Proposal.passenger.age", "ProposalDto.passengerAge"}),
@Field({"passenger.card", "passengerCard"}),
@Field({"Proposal.passenger.date", "ProposalDto.passengerDate"})
})
ProposalDto asProposalDto(Proposal proposal);
0x3 MapStruct教程
同selma类似,maven依赖如下:
<org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
<!-- mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
<!-- IntelliJ does not pick up the processor if it is not in the dependencies.
There is already an open issue for IntelliJ see https://youtrack.jetbrains.com/issue/IDEA-150621
-->
<scope>provided</scope>
</dependency>
和selma相同,mapstruct需要定义一个接口:
@Mapper
public interface MapStructConverter {
MapStructConverter MAPPER = Mappers.getMapper(MapStructConverter.class);
UserDto convertToUserDto(User user);
User convertToUser(UserDto userDto);
}
编译后,会生成一个实现类,如下:
public class MapStructConverterImpl implements MapStructConverter {
public MapStructConverterImpl() {
}
public UserDto convertToUserDto(User user) {
if (user == null) {
return null;
} else {
UserDto userDto = new UserDto();
userDto.setId(user.getId());
userDto.setUsername(user.getUsername());
userDto.setAge(user.getAge());
userDto.setAddress(user.getAddress());
return userDto;
}
}
public User convertToUser(UserDto userDto) {
if (userDto == null) {
return null;
} else {
User user = new User();
user.setId(userDto.getId());
user.setUsername(userDto.getUsername());
user.setAge(userDto.getAge());
user.setAddress(userDto.getAddress());
return user;
}
}
}
类似的,如果需要自定义字段映射,采用如下方法:
@Mapping(source = "orders", target = "orderItems")
@Mapping(source = "customerName", target = "name")
Customer toCustomer(CustomerDto customerDto);
网友评论