用 Kotlin 写 Spring Boot 应用程序
我在IntelliJ IDEA上看到一个类似于「是否应用Kotlin的设置?」的提示,于是试着点击了确定,它帮我在build.gradle中添加了设置。而且,我可以毫不费力地开始编写Kotlin,一点都不觉得不适应。非常顺利。
buildscript {
ext.kotlin_version = '1.0.0-beta-2423'
repositories {
jcenter()
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.0.RELEASE")
classpath("org.springframework:springloaded:1.2.4.RELEASE")
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'spring-boot'
apply plugin: 'idea'
idea {
module {
inheritOutputDirs = false
outputDir = file("$buildDir/classes/main/")
}
}
jar {
baseName = 'myproject'
version = '0.0.1-SNAPSHOT'
}
repositories {
jcenter()
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
我完全没有设置上述的build.gradle文件,它是由IDEA自动添加到原始的Spring Boot配置中的。如果使用IDEA进行Kotlin编译,它还会正确加载Spring Loaded。
我认为很多人都知道,IDEA(IntelliJ IDEA)有一个神奇的功能,即当我们将Java代码复制粘贴到Scala代码中时,它会自动将其转换为Scala代码。而这个功能在 JetBrains 公司开发的 Kotlin 中也像理所当然地存在。
将我在这篇文章中写的Application.java粘贴进去
http://qiita.com/seratch@github/items/5b4cf1194c3bbd9b55b0
就像这样的感觉。
package friendlist
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
@Configuration
@EnableAutoConfiguration
@ComponentScan
object Application {
@JvmStatic fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
}
尽管一开始看起来很不错,但是如果Kotlin的class或object没有带有open关键字,它们会被声明为final,因此Spring Boot在启动时会显示“请移除final关键字”并引发启动错误。
尽管对 Kotlin 不太熟悉,我还是试着模仿着做了一下,结果如下所示,可以运行。
https://kotlinlang.org/docs/tutorials/
package friendlist
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
@Configuration
@EnableAutoConfiguration
@ComponentScan
open class Application {
companion object {
@JvmStatic fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
}
}
我试着写了一个这样的控制器。
package friendlist.web
import friendlist.model.Friend
import friendlist.model.FriendResponse
import friendlist.model.FriendsResponse
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class FriendsController {
@RequestMapping("/")
fun home(): FriendsResponse {
return all()
}
@RequestMapping("/friends")
fun all(): FriendsResponse {
return FriendsResponse(Friend.findAll())
}
@RequestMapping("/friends/{id}")
fun show(@PathVariable id: Int): FriendResponse {
return FriendResponse(Friend.findById(id))
}
}
以下是一个关于model和DAO的示例。由于我想尝试使用static关键字,所以我只是这样写了一个例子。添加或不添加JvmStatic似乎都可以正常运行,但在Kotlin中处理这两种方式都可以吗?(我不太确定)
package friendlist.model
data class Friend(val id: Int, val name: String) {
companion object {
private val ALL_FRIENDS: List<Friend> = listOf(
Friend(1, "Alice"),
Friend(2, "Bob"),
Friend(3, "Chris"),
Friend(4, "Denis")
)
fun findAll(): List<Friend> {
return ALL_FRIENDS
}
fun findById(id: Int): Friend? {
return ALL_FRIENDS.find { f -> f.id == id }
}
}
}
package friendlist.model
data class FriendResponse(val friend: Friend?)
package friendlist.model
data class FriendsResponse(val friends: List<Friend>)
当我尝试访问时,响应主体很好地转换为了 JSON 格式。而且,即使我直接传递 Kotlin 的 List 或者 Friend 类型等数据,系统也能很好地进行处理,与 Scala 相比,与 Java 的互操作性非常顺畅。
$ curl -v localhost:8080/friends
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /friends HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 24 Nov 2015 15:03:48 GMT
<
* Connection #0 to host localhost left intact
{"friends":[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"},{"id":3,"name":"Chris"},{"id":4,"name":"Denis"}]}
$ curl -v localhost:8080/friends/1
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /friends/1 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 24 Nov 2015 15:03:50 GMT
<
* Connection #0 to host localhost left intact
{"friend":{"id":1,"name":"Alice"}}
$ curl -v localhost:8080/friends/123
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /friends/123 HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Tue, 24 Nov 2015 15:03:54 GMT
<
* Connection #0 to host localhost left intact
{"friend":null}
顺带一提,Qiita在pre标签中提供了Kotlin语法高亮,但似乎还无法正确识别”companion object { }”。暂时先改为Java吧。