项目场景:lombok、mapstruct同时使用时;pojo类get、set方法生成失败,mapstruct的实现类生成失败,只是单纯的new一个新对象。
目相关背景:
近期工作对于DTO、VO、PO相关的对象进行转化,接触到了mapstruct工具包,同时在项目中又使用了lombok,此时就出现了问题,两个工具同时使用时,lombok使用@Data、 @Setter、@Getter相关注解时,get、set方法生成失败,同时mapstruct的自动转换也生成失败。
问题描述
项目中遇到的问题:
简化代码:
<properties>
<org.mapstruct.version>1.5.0.Final</org.mapstruct.version>
<org.projectlombok.verion>1.18.12</org.projectlombok.verion>
</properties>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.verion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${org.mapstruct.version}</version>
</dependency>
<!-- 此处是在build标签中 -->
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.verion}</version>
</path>
</annotationProcessorPaths>
@Data
public class TestDTO {
private String name;
private String age;
}
@Data
public class TestVO {
private String name;
private String age;
}
@Mapper
public class DtoAssembler {
DtoAssembler INSTANCE = Mappers.getMapper(DtoAssembler.class);
TestDTO toDTO(TestVO testVO);
}
此时编译后,TestDTO并不会生成set 、get方法;
通过mapstruct 自动生成的实现类,只是new了一个新的对象出来,被未生成绑定值。
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2023-10-27T14:24:37+0800",
comments = "version: 1.5.0.Final, compiler: javac, environment: Java 1.8.0_281 (Oracle Corporation)"
)
public class DtoAssemblerImpl implements DtoAssembler{
@Override
public TestVO toRegionInfoVO(TestDTO testDTO) {
if ( testDTO == null ) {
return null;
}
TestVO testVO = new TestVO();
return testVO;
}
}
原因分析:
提示:这里填写问题的分析:
1、首先出现此问题之前,我确认了lombok是能够在IDE中正常使用的,项目中一直有使用,插件安装、包导入是没有问题的。所以不存在lombok相关的问题;
2、mapstruct的导入也是没有问题的;
3、尝试了在DTO、VO这类的相关类中去手动生成set、get方法,发现mapstruct能够正常生成实现类,此时排队了mapstruct本身的问题;
4、那会不会存在lombok与mapstruct不兼容的问题了? 因为单独使用都是正常的,我觉得这是一个方向了,然后在网上搜索了相关的问题,并未找到答案,只能登陆官网去查询,然后再中间找到了答案。
5、mapstruct官网的原文描述:
简单解释一下:首先MapStruct与Lombok是支持同时使用的。
从MapStruct 1.2.0. Beta1和Lombok 1.16.14版本开始,并分两种情况
1、如果您使用的是Lombok 1.18.16或更新版本,您还需要添加lombok-mapstruct-binding才能使Lombok和MapStruct一起工作。
2、如果您使用的是较旧的MapStruct或Lombok版本,解决方案是将要由Lombok修改的JavaBeans和要由MapStruct处理的映射器接口分成您项目的两个单独模块。然后Lombok将在第一个模块的编译期间运行,在第二个模块的编译期间运行MapStruct时,使bean类完整。
从我的情况来看,我属于第一种情况,那也就是说,我需要添加新的支持包;
解决方案:
添加新的三方支持包,此处用的是:0.2.0 版本,
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</dependency>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-mapstruct-binding</artifactId>
<version>${lombok-mapstruct-binding.version}</version>
</path>
此时,再次编译时,都成功生成方法与实现
@Data
public class TestDTO {
private String name;
private String age;
public String getName() { return this.name; }
public String getAge() { return this.age; }
public void setName(final String name) { this.name = name; }
public void setAge(final String age) { this.age = age; }
// ...此处省略就不复制了 equals、toString
}
@Data
public class TestVO {
private String name;
private String age;
public String getName() { return this.name; }
public String getAge() { return this.age; }
public void setName(final String name) { this.name = name; }
public void setAge(final String age) { this.age = age; }
// ...此处省略就不复制了 equals、toString
}
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2023-10-27T16:29:32+0100",
comments = "version: 1.5.0.Final, compiler: javac, environment: Java 1.8.0_281 (Oracle Corporation)"
)
public class DtoAssemblerImpl implements DtoAssembler{
@Override
public TestVO toRegionInfoVO(TestDTO testDTO) {
if ( testDTO == null ) {
return null;
}
TestVO testVO = new TestVO();
testVo.setName( testDTO.getName() );
testVo.setAge( testDTO.getAge() );
return testVO;
}
}
结论:
1、Lombok 1.18.16或更新版本,需要添加lombok-mapstruct-binding一起使用;
2、低版本由Lombok修改的JavaBeans和要由MapStruct处理的映射器接口分成您项目的两个单独模块。然后Lombok将在第一个模块的编译期间运行,在第二个模块的编译期间运行MapStruct时,使bean类完整。