驽马十驾

驽马十驾,功在不舍

目录
Kotlin 系列:Kotlin和 Java 混用时 开发以及编译的注意事项
/  

Kotlin 系列:Kotlin和 Java 混用时 开发以及编译的注意事项

分享一个Maven项目下kotlinJava混编,相关配置。

开篇

2020了,听说Kotlin不错,所以在公司的一个还没正式上线的项目中,选择了一个项目来试水。

该项目还在持续开发中,部分代码已经通过Java完成了,所以考虑采取新需求Kotlin,老的Java代码保持不变。

原本以为很容易,结果还是出现了不少乱七八糟的问题,这里记录下相关。

问题记录

Lombok

如果 Java的实体,假如用了lombok这个奇技淫巧,那么很遗憾,kotlin调用相关的 属性的时候,会提示找到对应的类。

处理办法是有几个

  • 去掉 lombok,生成getset方法,最笨的方式,是手动生成,我们要聪明点,利用lombok自带的功能来生成。方法是找到菜单栏:Refactor -> Delombok -> All lombok anntations,这个过程可能稍微慢一点,请耐心等待下。
  • 改写kotlin话,也可以利用Idea的自动转换。方法是找到菜单栏:Code -> Convert Java File to Kotlin File

Mybatis-plus

这个mybatis的扩展很不错,但是对kotlin的支持不够好,特别是对于参数的lambda话,支持不算好(基本使用貌似没问题,但是 github 有 issue 反馈)

我指的下述写法,请注意参数用的是Entity::peroerty这样的做法

        List<BlockUserList> list = queryWrapperChain()
                .select(BlockUserList::getId)
                .lt(BlockUserList::getEndDate, LocalDate.now())
                .list();

那么在新生成实体类的时候,有如下几个建议。

  • 利用MP 的代码生成器
  • 生成 Kotlin 格式的代码
  • 开启常量生成
  • MP 代码生成器的模板选择:VelocityTemplateEngine(因为默认的 Freemarkder生成存在 bug,不知道现在修复没)
  • 有需要,请自定义代码生成模板

下面我把我生成的实体类给一个 demo

open class BaseEntity {
    @TableField(fill = FieldFill.INSERT)
    @ApiModelProperty("创建人id")
    var createdUser: String = ""

    @TableField(fill = FieldFill.INSERT)
    @ApiModelProperty("创建时间")
    var createdTime: LocalDateTime = LocalDateTime.now()

    @TableField(fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty("修改人id")
    var updatedUser: String = ""

    @TableField(fill = FieldFill.INSERT_UPDATE)
    @ApiModelProperty("创建人时间")
    var updatedTime: LocalDateTime = LocalDateTime.now()

    companion object {
        const val CREATE_USER: String = "create_user"
        const val CREATE_TIME: String = "create_time"
        const val UPDATE_USER: String = "update_user"
        const val UPDATE_TIME: String = "update_time"
    }
}

@ApiModel(value="UserVolatile对象", description="xxx")
@UeOpen
class UserVolatile : BaseEntity() {

    @ApiModelProperty(value = "唯一标示")
    @TableId(value = "id", type = IdType.AUTO)
    var id: Long? = null

    @ApiModelProperty(value = "用户电话")
    var userTel: String? = null

    @ApiModelProperty(value = "记录时间")
    var recordDate: LocalDateTime? = null

    companion object {
        /**
         * 字段常量,含义:唯一标示
         */
        const val ID : String = "id"

        /**
         * 字段常量,含义:用户电话
         */
        const val USER_TEL : String = "user_tel"

        /**
         * 字段常量,含义:记录时间
         */
        const val RECORD_DATE : String = "record_date"
    }
}

请注意上面生成了字段常量,方便结合MP使用,比如通过生成字段常量来操作,肯定没有问题的。

  updateChain().eq(UserVolatile.USER_TEL, tel).update(userVolatile)

Maven编译

如果希望最终编译和打包的 jar 包正常运行,还需要做如下处理,在 maven 的 build 插件中引入kotlin 的相关编译插件。

    <build>
        <plugins>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
			<!--kotlin 的 maven 编译插件-->
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                	<!--kotlin 默认是 final 的,如果需要open,那么需该插件-->
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                    <!--kotlin 生成无参构造函数-->
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-noarg</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <args>
                        <arg>-Xjsr305=strict</arg>
                    </args>
                    <!--kotlin 编译插件启用,上面是引用-->
                    <compilerPlugins>
                        <plugin>spring</plugin>
                        <plugin>all-open</plugin>
                        <plugin>no-arg</plugin>
                    </compilerPlugins>
                    <!--插件的参数-->
                    <pluginOptions>
                    	<!--UeOpen 的注解的类会编译的时候不加 final-->
                        <option>all-open:annotation=com.uewell.gravid.frame.kt.compile.UeOpen</option>
                        <option>no-arg:annotation=com.uewell.gravid.frame.kt.compile.UeOpen</option>
                    </pluginOptions>
                    <jvmTarget>1.8</jvmTarget>
                </configuration>
            </plugin>

			<!--传统的 java编译-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <executions>
                    
                    <execution>
                        <id>default-compile</id>
                        <phase>none</phase>
                    </execution>
                   
                    <execution>
                        <id>default-testCompile</id>
                        <phase>none</phase>
                    </execution>
                    <execution>
                        <id>java-compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>java-test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <!--编译的时候把参数添加进去-->
                    <compilerArgument>-parameters</compilerArgument>
                </configuration>
            </plugin>
        </plugins>
    </build>

需要有如下几个注意事项

  1. kotlin的编译需要在 传统的 maven 编译之前,大家有需要,复制后改改就行了。
  2. allopennoarg这2个插件的作用我就不细表了,大家自行百度

结语

不多说了,直说一句:kotlin真香!

不积跬步,无以至千里。不积小流,无以成江海。
评论