用 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吧。

广告
将在 10 秒后关闭
bannerAds