当使用较高版本的maven,比如3.6.3+
且配置较高的java版本,比如java17
按本文方法,可以用这份maven环境兼容java17代码和java8代码的编译
核心概念说明:
maven本身由java编写,它的运行需要java环境,需要的java版本视maven版本而定.
如果没有特意指定,maven会利用自身依赖的java环境去编译代码.
但如果maven依赖的java版本和代码版本不一致,可以进行手动指定,
即 maven自身依赖的版本(可以理解为maven需要的运行环境jre)
和用来编译代码的的版本(可以理解为编译功能javac的版本)
这两块是可以独立化的,
并不是maven依赖java8就只能编译java8,依赖java17就只能编译17
mvn运行和编译独立化的情形分为两大类:
1. maven依赖的java版本低,比如依赖java8,却需要编译java17代码,此情况是可以独立配置的,本质上还是需要提供java17的编译环境.个人觉得这种情形的兼容性不好,直接放弃采用下述第二种情形.
2.maven依赖的java版本高,比如依赖java17,却需要编译java8代码,此情况的独立配置较为便利,因为java17等高版本是可以兼容低版本java的编译行为的.以Spring项目为例,需要使用低版本编译的项目,在pom.xml的<properties>标签中添加如下配置:
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
目的就是明确告诉依赖高版本java的maven:本项目需要用指定低版本的java来编译,高版本maven是具备向下兼容的能力的.
如果上述配置没有生效,那么可能是maven版本也过低,可以手动指定maven插件的版本,同样在pom.xml文件中插件标签内添加如下插件:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>手动指定一个较高的版本-比如3.10.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
之所以描述这个问题,是因为我这边使用jenkins自动化部署,想偷个懒,只配置一个maven和java环境,兼容java17和java8.我使用的是maven3.6.3配合java17,按如上配置可以正常编译java8项目.
注意一些坑:
1. lombok会有编译阶段的行为,所以它的版本太低会引起编译问题,如果报field无法获取之类的错,可以升下lombok版本试下,我使用的lombok版本是1.18.30
2. 实测下来,真正的java8环境好像对于java6,java7这种更旧版本的语法更具包容性,而java17环境指定以java8版本来编译,包容性变差了,强制要求语法最低也要符合java8规范;
比如要求sun.misc.BASE64Decoder替换为java.util.Base64;
遇到这种情况,把项目里部分老旧的语法改一改,
这个方向肯定是正确的:依赖java17的maven通过手动指定编译版本,是可以编译java8项目的.
如果工作量太大,建议还是放弃,降版本吧 ^_^