SpringBoot3下Kotlin和Java混编

一、背景

目前已有Java语言编写的SpringBoot3脚手架项目,想要使用Kotlin继续开发,所以需要和Java进行混编。

二、如何混编

2.1 项目的环境介绍

  1. 语言:Java17,Kotlin 1.9.22
  2. 框架: SpringBoot3
  3. 构建工具: maven
  4. 项目结构: 多模块(module)

选择maven是因为脚手架项目就是用maven构建,并且个人比较熟悉maven。

2.2、期待达到的效果

主要想要达成两个效果:

  1. 在已有的纯Java模块内,添加Kotlin语言,支持两者编译。
  2. 能够在新创建的模块内,实现纯Kotlin语言或者Java和Kotlin混编开发。
  3. 不管是已有模块和新建模块,都能够正常编译、打包、运行、推送、调用和被调用,即和纯Java语言开发一样的构建效果。

2.3、支持Kotlin构建

不管是新模块还是已有模块,想要支持Kotlin编译步骤都是一样的。

2.3.1、版本号管理

首先在依赖管理(一般是最顶级父工程中)中加入Kotlin的版本和依赖

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>17</maven.compiler.source>
  <maven.compiler.target>17</maven.compiler.target>
  <!--  kt版本 -->
  <kotlin.version>1.9.22</kotlin.version>
</properties>

2.3.2、依赖管理

然后在依赖管理中引入kt依赖

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib-jdk8</artifactId>
      <version>${kotlin.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-stdlib</artifactId>
      <version>${kotlin.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-test</artifactId>
      <version>${kotlin.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-test-junit5</artifactId>
      <version>${kotlin.version}</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-allopen</artifactId>
      <version>${kotlin.version}</version>
    </dependency>
  </dependencies>
</dependencyManagement>
​
<dependencies>
  <dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib-jdk8</artifactId>
  </dependency>
  <dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib</artifactId>
  </dependency>
  <dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-test-junit5</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-allopen</artifactId>
  </dependency>
  <dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-kotlin</artifactId>
  </dependency>
</dependencies>

2.3.3、顶级父模块构建管理

这里是指最顶级父没有代码的工程的build配置,如果只有一个模块,可以直接看下一步,对于是否需要在顶级父模块这样配置,目前还没有验证过,不过配置了不会有问题。

添加build构建插件

<build>
  <plugins>
    <plugin>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-maven-plugin</artifactId>
      <version>${kotlin.version}</version>
      <executions>
        <execution>
          <id>compile</id>
          <phase>compile</phase>
          <goals>
            <goal>compile</goal>
          </goals>
        </execution>
        <execution>
          <id>test-compile</id>
          <phase>test-compile</phase>
          <goals>
            <goal>test-compile</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <jvmTarget>${maven.compiler.target}</jvmTarget>
        <compilerPlugins>
          <plugin>spring</plugin>
          <plugin>all-open</plugin>
        </compilerPlugins>
      </configuration>
    </plugin>
  </plugins>
</build>

这里的插件配置在父工程中,如果不是多模块请参照下面实际代码模块的配置。

2.3.4、具有代码的模块构建配置

只要是有代码的模块,都需要再额外进行Kotlin构建配置

<build>
  <plugins>
    <plugin>
      <groupId>org.jetbrains.kotlin</groupId>
      <artifactId>kotlin-maven-plugin</artifactId>
      <version>${kotlin.version}</version>
      <executions>
        <execution>
          <id>compile</id>
          <phase>compile</phase>
          <goals>
            <goal>compile</goal>
          </goals>
        </execution>
        <execution>
          <id>test-compile</id>
          <phase>test-compile</phase>
          <goals>
            <goal>test-compile</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <!--jvm版本配置,一般和项目JDK版本一致,IDE会自动识别-->
        <jvmTarget>${maven.compiler.target}</jvmTarget>
        <!--下面的all-open插件会将Kotlin的默认访问级别编译时设置为public-->
        <compilerPlugins>
          <plugin>spring</plugin>
          <plugin>all-open</plugin>
        </compilerPlugins>
        <!--这里需要指定Kotlin的源码目录,一般和Java源码目录统计,Java源码目录不需要配置,约定的src/main/java会自动识别-->
        <sourceDirs>
          <sourceDir>src/main/kotlin</sourceDir>
        </sourceDirs>
      </configuration>
      <dependencies>
        <!--这里需要添加依赖配置上面的all-open编译插件-->
        <dependency>
          <groupId>org.jetbrains.kotlin</groupId>
          <artifactId>kotlin-maven-allopen</artifactId>
          <version>${kotlin.version}</version>
        </dependency>
      </dependencies>
    </plugin>
  </plugins>
</build>

主要有几点需要注意:

  1. 每个有代码的项目都需要配置plugin。
  2. jvmTarget和项目JDK版本一致,IDE会识别出来,开发的时候会以pom文件配置为准。
  3. 编译的时候all-open插件需要对应的依赖支持,如果不配置对应依赖构建会报错找不到插件。
  4. 需要明确指定Kotlin源码的路径,否则会无法编译Kotlin代码。