大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全家桶1年46,售后保障稳定
简介
MapStruct是满足JSR269规范的一个Java注解处理器,用于为Java Bean生成类型安全且高性能的映射。它基于编译阶段生成get/set代码,此实现过程中没有反射,不会造成额外的性能损失。
您所要做的就是定义一个mapper接口(@Mapper),该接口用于声明所有必须的映射方法。在编译期间MapStruct会为该接口自动生成实现类。该实现类使用简单的Java方法调用来映射source-target对象,在此过程中没有反射或类似的行为发生。
性能
优点
与手工编写映射代码相比
- MapStruct通过生成冗长且容易出错的代码来节省时间。
与动态映射框架相比
- 简单泛型智能转换;
- 效率高:无需手动 set/get 或 implements Serializable 以达到深拷贝;
- 性能更高:使用简单的Java方法调用代替反射;
- 编译时类型安全:只能映射相同名称或带映射标记的属性;
- 编译时产生错误报告:如果映射不完整(存在未被映射的目标属性)或映射不正确(找不到合适的映射方法或类型转换)则会在编译时抛出异常。
使用
1、引入 Pom
方法一
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.2.0.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.2.0.Final</version>
</dependency>
方法二
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.0.Final</version>
</dependency>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
<encoding>UTF-8</encoding>
<annotationProcessorPaths>
<!-- 必须要加, 否则生成不了 MapperImpl 实现类 -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.0.Final</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
2、注入方式
- Spring 注入方式
/**
* @author Lux Sun
* @date 2021/2/22
*/
@Mapper(componentModel = "spring")
public interface ApiMapper {
}
- ClassLoader 加载方式
/**
* @author Lux Sun
* @date 2021/2/22
*/
@Mapper
public interface ApiMapper {
ApiMapper INSTANCE = Mappers.getMapper(ApiMapper.class);
}
3、案例(ApiVO 转 ApiDTO)
ApiMapper
/**
* @author Lux Sun
* @date 2021/2/22
*/
@Mapper(componentModel = "spring")
public interface ApiMapper {
// ClassLoader 加载方式
ApiMapper INSTANCE = Mappers.getMapper(ApiMapper.class);
/**
* ApiVO 转 ApiDTO
* @param apiVO
*/
@Mapping(source = "method", target = "apiMethod")
ApiDTO apiVoToApiDto(ApiVO apiVO);
}
ApiMapperTest
@Resource
private ApiMapper apiMapper;
/**
* ApiVO 转 ApiDTO
* @param
* @return void
*/
public void apiVoToApiDtoTest() {
// 创建 ApiPOList
ApiPO apiPO1 = ApiPO.builder().name("apiName1").build();
List<ApiPO> apiPOList = Lists.newArrayList();
apiPOList.add(apiPO1);
// 创建 ApiConf
ApiVO.ApiConf apiConf = ApiVO.ApiConf.builder().id("123456").build();
// 创建数字 List
List<Integer> numberList = Lists.newArrayList();
numberList.add(1);
numberList.add(2);
// 创建 ApiVO
ApiVO apiVO = ApiVO.builder().name("apiName").method(1)
.apiPOList(apiPOList).apiConf(apiConf)
.list(numberList).build();
// 转换结果 ApiDTO
// ClassLoader 调用方式
ApiDTO apiDTO = ApiMapper.INSTANCE.apiVoToApiDto(apiVO);
// Spring 调用方式
// ApiDTO apiDTO = apiMapper.apiVoToApiDto(apiVO);
System.out.println(apiDTO);
}
结果输出
ApiDTO(name=apiName, apiMethod=1, apiConf=ApiDTO.ApiConf(id=123456, open=null), apiPOList=[ApiPO(name=apiName1, method=null, apiConf=null, apiPOList=null)], list=[1, 2])
原理
通过 JSR 269 Java注解处理器自动生成该文件
ApiMapperImpl
package com.luxsun.platform.lux.kernel.common.convert;
import com.luxsun.platform.lux.kernel.common.domain.dto.ApiDTO;
import com.luxsun.platform.lux.kernel.common.domain.dto.ApiDTO.ApiConf;
import com.luxsun.platform.lux.kernel.common.domain.po.ApiPO;
import com.luxsun.platform.lux.kernel.common.domain.vo.ApiVO;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Generated;
import org.springframework.stereotype.Component;
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2021-02-22T14:48:03+0800",
comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_121 (Oracle Corporation)"
)
@Component
public class ApiMapperImpl implements ApiMapper {
@Override
public ApiDTO apiVoToApiDto(ApiVO apiVO) {
if ( apiVO == null ) {
return null;
}
ApiDTO apiDTO = new ApiDTO();
apiDTO.setApiMethod( apiVO.getMethod() );
apiDTO.setName( apiVO.getName() );
apiDTO.setApiConf( apiConfToApiConf( apiVO.getApiConf() ) );
List<ApiPO> list = apiVO.getApiPOList();
if ( list != null ) {
apiDTO.setApiPOList( new ArrayList<ApiPO>( list ) );
}
else {
apiDTO.setApiPOList( null );
}
apiDTO.setList( integerListToStringList( apiVO.getList() ) );
return apiDTO;
}
protected ApiConf apiConfToApiConf(com.luxsun.platform.lux.kernel.common.domain.vo.ApiVO.ApiConf apiConf) {
if ( apiConf == null ) {
return null;
}
ApiConf apiConf1 = new ApiConf();
apiConf1.setId( apiConf.getId() );
apiConf1.setOpen( apiConf.getOpen() );
return apiConf1;
}
protected List<String> integerListToStringList(List<Integer> list) {
if ( list == null ) {
return null;
}
List<String> list1 = new ArrayList<String>( list.size() );
for ( Integer integer : list ) {
list1.add( String.valueOf( integer ) );
}
return list1;
}
}
Ps:这就是为什么 mapstruct 的效率比较高的原因,相比于反射获取对象进行拷贝的方法,这种更贴近于原生 get/set 方法的框架显得更为高效。这个文件是通过在 mapper 中的注解,使用生成映射器的注解处理器从而自动生成了这段代码。
注意事项
- 开发过程中遇到修改属性时,重新启动项目还是复制的时候新添加的属性为 null,此时,因为自动生成的实现类并没有重新编译,需要手动在 target 包中找到删除,再重新启动即可!
FAQ
- MapStruct – Lombok & Maven 版本关系
-
MapStruct – Consider defining a bean of type in your configuration.
- MapStruct – No property named “XXX“ exists in source parameter(s). Did you mean “null“?
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/213391.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...