Spring Framework从5.0开始加入了完整的Kotlin语言支持~使用Kotlin DSL风格的构建语法,能切实感受到Java语言缺失的那份开发的快感。配合上免配置的Spring Boot框架,更是如虎添翼。
当然即便经过了从2016年到2018年的不断融合,Kotlin和Spring的结合依然还存在不少需要注意的地方。这篇文章主要列出果子开发中跳的坑,以及摸索(Google)出的解决方案。
Domain类
作为保存数据资源最基础的POJO对象,Kotlin中的data class
可谓是满足了常见的那些根本不想写的功能。
一个常见的POJO需要getter、setter、equals、hashCode、toString方法,在没有IDE功能之前,get和set方法都是手写的;
然后各大IDE推出了快速创建getter、setter的功能,这项功能在宇宙级IDE IntelliJ IDEA中肯定提供,快捷键是Alt+Insert(Cmd+N on macOS)。但美中不足的是,如果修改了类的定义,比如添加或者删除了类的成员变量,这些方法需要手动相应修改;
现在Kotlin将这种操作简化成一个关键词data class
,不仅不需要手写POJO方法,而且在类成员定义发生变化的时候,完全不需要更新代码!
比如这是一个找回密码的令牌类
1 | typealias TokeType = String |
这段代码不仅使用了data class
来设置数据类,而且使用了typealias
语句声明一个类型别名。
类型别名能在IDE的类型提示中以注释的形式展示出来,更直观。
可以注意到Kotlin的类型定义十分适合需要大量DTO、VO的地方,简单几行便能创建一个类型安全还具有高度可读性的数据类。
反观Java选手,提供相同功能的Java类,则需要至少3倍的代码量。 对比之下 可读性下降到无法直视的地步。
1 |
|
如果还需要加上@Nullable
@NotNull
等null类型标记,更体现Kotlin的优越性。
所以Kotlin语言对于大型项目的开发和维护可是一副五星装备!
而且作为用在Kotlin上的代码注释KDoc
相比JavaDoc
来讲,编写舒适度也有十足提升。
它支持Markdown语法,顺带的也能使用[]()
语法来引用函数参数、函数名的超链接。
@return
@param
标签也有相同的写法,完全没有学习成本。
构造器和依赖注入
Kotlin类支持主从构造器,主构造器可以放在类名后的括号里直接申明,就如同上面data class
里class后面的括号。
申明继承也是使用 :
完成的。
使用Spring 依赖注入框架,配合上Kotlin可以有很漂亮的代码
比如这是一个Controller,需要注入一个Service。可以使用的方式有
-
设置一个类型为
Service?
的域,然后设置@Autowired
注解1
2
3
4class AccountController{
private var accountService: AccountService?
}这样操作以后每次调用都需要判断null
-
使用
lateinit var
声明一个类型为Service
的域,然后设置@Autowired
注解1
2
3
4class AccountController{
private lateinit var accountService: AccountService
}这样使用至少不用判断null了,可是它还是个
var
在代码高亮的时候可能会不好看 -
在类的构造器上直接声明
val servie: Service
,不需要注解!1
2
3class AccountController(
private val accountService: AccountService
)这样既没有可变性,又没有可空性,简直完美😝
单例和Object Expression
Java中的单例模式比较废代码,在Kotlin中只需要object一个标注就行。
比如下面是一个关于密码的帮助类
1 | /**密码相关的帮助类*/ |
在Kotlin中调用这个类的方法只需要使用类名即可,不需要获取到INSTANCE
实例类似的方法。
可是在在Java中调用Kotlin代码,则需要先通过获取INSTANCE
实例,再进行操作。
Gradle
如果你使用Gradle,请往下阅读 根据Gradle新版本(4.0+)的文档,有几个比较大的变化。
-
Gradle plugins DSL 还记得
build.gradle
默认生成的代码头上会有一段1
2
3
4
5
6
7
8
9buildscript {
repositories {
xxx
}
dependencies {
classpath 'xxxxxx'
}
}
apply plugin: xxx这段代码是应用Gradle plugin老旧的方法。
如果使用plugins DSL,可以变成短短的样子。 比如这是Kotlin + Spring Boot常用的插件组合
1
2
3
4
5
6
7
8plugins {
id "org.springframework.boot" version "2.0.1.RELEASE"
id "io.spring.dependency-management" version "1.0.5.RELEASE"
id "org.jetbrains.kotlin.jvm" version "1.2.40"
id "org.jetbrains.kotlin.plugin.spring" version "1.2.40"
id "org.jetbrains.kotlin.plugin.jpa" version "1.2.40"
id "org.jetbrains.dokka" version "0.9.16"
}DSL写法的一个不足是,它的版本号是字面量,以字符串的形式卸载代码里。并不能使用之前常见的作法,将版本号作为变量使用。
-
compile -> implementation
在新版本的Gradle上,如果你曾经运行过
Tasks > help > dependencies
,能看到compile部分被加上了Deprecated的标记compile - Dependencies for source set ‘main’ (deprecated, use 'implementation ’ instead).
那他们为什么要这么做呢。
原因是在你打包的项目中,compile会把你的文件和你引用的包一起暴露给引用者。而implementation就不会。
不过作为开发者的你确实想要暴露给外一个组件呢,比如编写的项目包含有一个名叫
project_api
的组件,或者它是个project_library
的库组件。 这时候只需要使用api
标记。1
2
3
4
5
6plugins {
id 'java-library'
}
dependencies {
api 'xxxxx'
}注意这里使用了一个叫 java-library 的插件,有了它才能使用api标记,不然代码提示里的
apiElements
并不是你需要的。
那么如果跟上时代呢
其实很简单,只需把
compile
一键替换成implentation
即可!其实还有,将
runtime
替换成runtimeOnly
;testCompile
替换成testImplementation
。 将像暴露给外的组件使用api
标记。 -
Fat jar,打包可执行的Kotlin项目
我们分发项目成果的时候都希望简单一些,如果能直接打包一个jar丢过去,对方就能运行了那便是坠好的。 Spring Boot 的插件提供了一个叫
bootJar
的任务,可以很好的完成目标任务。它在Tasks > build > bootJar
下面, 会将生成的jar文件放到builds/libs
下面,直接使用Java -jar
运行就好。因为所有的依赖项都在一个jar包里,所以体积会有点大。如果没有使用Spring Boot呢,那就只能自己手动操作。 为jar任务添加一个打包操作即可。参考来源
1
2
3
4
5jar {
from {
configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
}
常见问题
¶写了Controller方法,却不能在Spring MVC Panel看到接口定义
如果是Java,请注意自己写的类和方法是不是public
的。
如果是Kotlin,似乎现在的版本暂时还看不到。
¶设置了301转发,第二次修改之后永远看不到更改变化
可能你是浏览器301缓存的受害者,果子曾经在nginx上为一个域名设置了301转发,可是第一次设置错误。 使用Chrome浏览器打开发现不对,再次修改nginx配置文件却一直等不到生效。多次debug也失效
鸡汁的我选择用 隐身模式 打开,验证设置是正确的。 然后搜索啊搜索,最后发现是Chrome浏览器的301缓存的锅,而且这个缓存是近乎永久的🌚 参见大佬们的讨论得出解决方案如下
- 打开 chrome://net-internals/ (或者 about://net-internals/ )
- 点击右上角黑色的向下的小箭头▼
- 选择清除缓存 Clear cache
- 大功告成
¶为什么我在Kotlin下面没有一些代码提示
IntelliJ IDEA的Spring插件,主要是面向Java平台的, 在Kotlin语境下就看不到比如Spring Data Repository的语法提示; 也没有JPA的图标和语法检查。
这都是以后期望厂家跟进修复的功能