mapstruct 文档:
MapStruct 1.6.0 Reference Guide
背景
基于 spring-boot-starter-web 的普通web项目,使用了lombok插件、mapstruct插件辅助开发。
现要求代码开发规范要过 maven-checkstyle-plugin 插件的检测。
maven-checkstyle-plugin 的代码风格配置文件中要求 if 关键和后面的括号不能有空格,如:
if(po == null){
return null;
}...
而正常的代码规范是有空格的,比如:
经过maven打包构建发现,checkstyle 插件指定在 package 阶段进行检测,如下:
执行 mvn clean package,报错如下:
mapstruct的原理
MapSturct 是一个生成类型安全, 高性能且无依赖的 JavaBean 映射代码的注解处理器(annotation processor)
简单的说下,想了解具体的自行百度。
在 compile 过程中:
- javac对源代码进行分析,生成了一棵抽象语法树(AST)
-
过程中调用了实现 “jsr 269 API”的 mapstruct,mapstruct在 target目录下生成了 generated-sources目录,为bean转换的java实现类,如图:
这里说一下编译时解析,有两种方式:
- APT(Annotation Processing Tool) 已过时
- API(Pluggable Annotation Processing API)
mapstruct就是用了第二种方式 注解解析器
- 编译 .java -> .class
为什么lombok不受影响
lombok和mapstruct都是在编译时做手脚,但lombok和 cglib动态代理一样,用的那个字节码直接写入的技术,不会生成 java源文件,也就不受 checkstyle插件的影响。
原因
checkstyle 插件扫到了 target 目录下 mapstruct 用 freemarker 基于 ftl 模版生成的 impl 实现类,如图:
解决思路
弃用 mapstruct,或等mapstruct生成好之后把impl方法复制过来改改格式。。。
当然可以,不过太累了,也不是个常规的办法。checkstyle插件目的是约束开发代码的规范,直接指定其检测的目录不行吗?
当然可以,不过我这里插件配置是甲方规定的,到时候这块是在自动化构建ci/cd过程中人家配置的,人家指定的规则可不配合你改,人家就想都检测。
一般人也不会去检测,就算自己想检测规范大不了配置个范围,比如:
配置代码检测的范围:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<configLocation>style/checkstyle.xml</configLocation>
<failsOnError>false</failsOnError>
<!-- 配置代码检测的范围 -->
<!-- <sourceDirectories>-->
<!-- <sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>-->
<!-- <sourceDirectory>${project.build.testSourceDirectory}</sourceDirectory>-->
<!-- </sourceDirectories>-->
</configuration>
<executions>
<execution>
<id>checkstyle-check</id>
<phase>package</phase>
<!-- <phase>compile</phase>-->
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
覆盖 mapstruct 的模版,指定使用自己的 ftl 模版
行不通,因为他是“编译时解析”无法正常覆盖!而且,查看了mapstruct的官方文档和源代码,没有暴露任何修改ftl的spi。既然覆盖不了,fork一份源码自己改不行吗?
当然可以,不过暂时没去这么做。-
仔细看maven构建的生命过程,mapstruct是发生在compile这步,而 checkstyle是发生在package这步之前,如图:
那我们在 target 目录下 generated-sources 文件夹等 compile 结束后 class文件都生成好之后,把这个临时的java文件夹给删了不就好了?可以,配置如下:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<delete dir="${project.build.directory}/generated-sources" />
</target>
</configuration>
</execution>
</executions>
</plugin>
【建议放在checkstyle插件前,这样即便是checkstyle指定检测环节为compile也不影响。checkstyle如果指定检测环节在compile之前那就更不影响了因为那时候mapstruct还没上岗工作】
上面加的删除generated-sources步骤,在构建中,如图:
mapstruct能否配置删了自己渲染的 java文件夹?
不能,因为他只负责生产java源文件即 generated-sources目录下的文件,后面的“编译到class”这一步他已经“歇班”了。
测试:
最后
如果你能改checkstyle的扫描范围当然是最合理的了。
如果不考虑那点儿性能,用BeanUtils反射也挺好。