
目录
1、性能分析
2、什么是Mapstruct
4、普通使用方法
4.1 创建DO
4.2创建DTO
4.3创建一个基础的Mapstruct类
4.4创建映射器接口
5、spring依赖注入使用方法
6、总结
7、源码和官网
在我们平时开发过程中,往往会涉及到,对象和对象直接的转化,而看到这个需求时直接想到的就是反射和BeanUtils工具,但是这个之间的效率往往是非常低的。
public class ReflectTest {
private static final int LIMIT_NUM = 1;
@Test
public void beanUtil() {
long start = System.currentTimeMillis();
OrderDTO orderDto = new OrderDTO();
orderDto.setName("mapstruct 测试");
orderDto.setCost(12L);
orderDto.setPrice("13");
orderDto.setWeight(123L);
orderDto.setIsDeleted(false);
orderDto.setIsFinish(true);
orderDto.setGmtCreat(LocalDateTime.now());
orderDto.setGmtModified(LocalDateTime.now());
ItemDTO itemDTO = new ItemDTO();
itemDTO.setItemName("衬衫");
itemDTO.setPrice(12L);
orderDto.setItemList(Arrays.asList(itemDTO));
for (int i = 0; i < LIMIT_NUM; i++) {
final Order order = new Order();
BeanUtils.copyProperties(orderDto, order);
}
long end = System.currentTimeMillis();
System.out.println("BeanUtils耗时:"+(end - start ) + "ms");
mapstruct();
}
@Test
public void mapstruct() {
long start = System.currentTimeMillis();
OrderDTO orderDto = new OrderDTO();
orderDto.setName("mapstruct 测试");
orderDto.setCost(12L);
orderDto.setPrice("13");
orderDto.setWeight(123L);
orderDto.setIsDeleted(false);
orderDto.setIsFinish(true);
orderDto.setGmtCreat(LocalDateTime.now());
orderDto.setGmtModified(LocalDateTime.now());
ItemDTO itemDTO = new ItemDTO();
itemDTO.setItemName("衬衫");
itemDTO.setPrice(12L);
orderDto.setItemList(Arrays.asList(itemDTO));
for (int i = 0; i < LIMIT_NUM; i++) {
final Order order = new Order();
OrderMapper.INSTANCE.updateOrder(orderDto, order);
}
long end = System.currentTimeMillis();
System.out.println("mapstruct耗时:"+(end - start ) + "ms");
}
}
平均结果:
BeanUtils耗时:150ms
mapstruct耗时:10ms
从上面可以看出BeanUtils和Mapstruct的性能差距还是蛮大的。
当然很多人也会说放射如果通过缓存性能能极大的提升,但是问题是,大部分的情况下我们是无法满足缓存的条件,而且这种反射往往比较麻烦,所以今天来看看Mapstruct这个技术。
原文
MapStruct is a code generator that greatly simplifies the implementation of mappings between Java bean types based on a convention over configuration approach.
The generated mapping code uses plain method invocations and thus is fast, type-safe and easy to understand.
Mapsturct 是一个通过配置公约的一种代码生成器,它大大简化了Java Bean类型之间的映射的实现,而且类型安全,性能高,使用简单。
3、准备工作
引入依赖,java11环境时
11 11 1.3.1.Final 3.6.1 org.glassfish.jaxb jaxb-runtimeorg.projectlombok lombokorg.mapstruct mapstruct${mapstruct.version} org.mapstruct mapstruct-processor${mapstruct.version} provided
package com.eagle.example.mapstruct.dataobject;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class Order implements Serializable {
private String title;
private Long price;
private Long weight;
private Long cost;
List- itemList;
private String isDeleted;
private Boolean isFinish;
private String gmtCreat;
private LocalDateTime gmtModified;
}
package com.eagle.example.mapstruct.dataobject;
import lombok.Data;
@Data
public class Item {
private String itemName;
private Long price;
}
package com.eagle.example.mapstruct.dto;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class OrderDTO implements Serializable {
private String name;
private String price;
private Long weight;
private Long cost;
private List itemList;
private Boolean isDeleted;
private Boolean isFinish;
private LocalDateTime gmtCreat;
private LocalDateTime gmtModified;
}
package com.eagle.example.mapstruct.dto;
import lombok.Data;
@Data
public class ItemDTO {
private String itemName;
private Long price;
}
package com.eagle.example.mapstruct.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class OrderInfoDTO implements Serializable {
private String name;
private String price;
}
可以编写一些基础方法和通用功能,因为随着Localdate的引入DO也都使用了Localdate类型,但是Mapstruct对Localdate支持比较弱,所以引入
package com.eagle.example.mapstruct.convert;
import org.mapstruct.Mapper;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Mapper(imports = {LocalDateTime.class, LocalDate.class})
public interface baseMapstruct {
}
当前例子是比较全的一种形态,所以很多不需要使用的自己酌情删除
package com.eagle.example.mapstruct.convert;
public class BooleanStrFormat {
private static final String Y_CHAR = "Y";
private static final String N_CHAR = "N";
public String toStr(Boolean isDisable) {
if (isDisable) {
return Y_CHAR;
} else {
return N_CHAR;
}
}
public Boolean toBoolean(String str) {
if (str.equals(Y_CHAR)) {
return true;
} else {
return false;
}
}
}
package com.eagle.example.mapstruct.convert;
import com.eagle.example.mapstruct.dataobject.Order;
import com.eagle.example.mapstruct.dto.OrderDTO;
import com.eagle.example.mapstruct.dto.OrderInfoDTO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Mappings;
import org.mapstruct.ap.internal.util.Strings;
import org.mapstruct.factory.Mappers;
import java.util.List;
@Mapper(uses = BooleanStrFormat.class)
public interface OrderMapper extends baseMapstruct {
OrderMapper INSTANCE = Mappers.getMapper(OrderMapper.class);
String Y_CHAR = "Y";
String N_CHAR = "N";
@Mappings({
@Mapping(source = "name", target = "title"),
@Mapping(target = "gmtCreat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
@Mapping(target = "price", qualifiedByName = "toLong")
})
Order orderDto2Order(OrderDTO orderDTO);
@Mappings({
@Mapping(source = "title", target = "name"),
@Mapping(target = "gmtCreat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
@Mapping(target = "price", qualifiedByName = "toStr")
})
OrderDTO order2OrderDto(Order order);
default Long toLong(String price) {
if (Strings.isEmpty(price)) {
return 0L;
} else {
return Long.parseLong(price);
}
}
default String toStr(Long price) {
if (price != null) {
return price.toString();
} else {
return "0";
}
}
List orderDto2Order(List orderDTOList);
@Mappings({
@Mapping(source = "name", target = "title"),
@Mapping(target = "gmtCreat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
@Mapping(target = "price", qualifiedByName = "toLong")
})
void updateOrder(OrderDTO orderDTO, @MappingTarget Order order);
@Mappings({
@Mapping(source = "orderInfoDTO.name", target = "title"),
@Mapping(source = "orderDto.gmtCreat", target = "gmtCreat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
@Mapping(source = "orderInfoDTO.price", target = "price", qualifiedByName = "toLong")
})
Order getUserByOrderDTOAndOrderInfoDTO(OrderDTO orderDto, OrderInfoDTO orderInfoDTO);
@Mappings({
@Mapping(source = "orderInfoDTO.name", target = "title"),
@Mapping(source = "orderDto.gmtCreat", target = "gmtCreat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
@Mapping(target = "price", source = "orderDto.price")
})
Order getUserByOrderDTOAndOrderInfoDTOChoicePrice(OrderDTO orderDto, OrderInfoDTO orderInfoDTO);
}
package com.eagle.example.mapstruct.convert;
import org.springframework.stereotype.Component;
@Component
public class SpringBooleanStrFormat {
private static final String Y_CHAR = "Y";
private static final String N_CHAR = "N";
public String toStr(Boolean isDisable) {
if (isDisable) {
return Y_CHAR;
} else {
return N_CHAR;
}
}
public Boolean toBoolean(String str) {
if (str.equals(Y_CHAR)) {
return true;
} else {
return false;
}
}
}
package com.eagle.example.mapstruct.convert;
import com.eagle.example.mapstruct.dataobject.Order;
import com.eagle.example.mapstruct.dto.OrderDTO;
import org.mapstruct.InjectionStrategy;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.ap.internal.util.Strings;
import java.util.List;
@Mapper(componentModel = "spring", injectionStrategy = InjectionStrategy.CONSTRUCTOR, uses = SpringBooleanStrFormat.class)
public interface SpringOrderMapper extends baseMapstruct {
@Mappings({
@Mapping(source = "name", target = "title"),
@Mapping(target = "gmtCreat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
@Mapping(target = "price", qualifiedByName = "toLong")
})
Order orderDto2Order(OrderDTO orderDTO);
@Mappings({
@Mapping(source = "title", target = "name"),
@Mapping(target = "gmtCreat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
@Mapping(target = "price", qualifiedByName = "toStr")
})
OrderDTO order2OrderDto(Order order);
default Long toLong(String price) {
if (Strings.isEmpty(price)) {
return 0L;
} else {
return Long.parseLong(price);
}
}
default String toStr(Long price) {
if (price != null) {
return price.toString();
} else {
return "0";
}
}
List orderDto2Order(List orderDTOList);
}
github:eagle-example: 项目例子集合
官网:MapStruct – Java bean mappings, the easy way!