精通Spring Boot 3 : 使用 Kotlin 创建用户应用程序项目

如果 Kotlin 是您首选的编程语言(假设您已经安装了 Kotlin),本节将演示如何使用 Kotlin 而不是 Java 创建 Users App 项目。如果您访问 start.spring.io 并选择 Kotlin 编程语言,您可以生成项目并导入到您喜欢的 IDE 中。请参见图 1-8。



在将项目导入您喜欢的 IDE 后,打开 build.gradle 文件,您应该会看到以下内容。请注意,我们正在向其中添加额外的信息,比如引导依赖和测试声明。请参见清单 1-9。

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
    id 'org.springframework.boot' version '3.2.4'
    id 'io.spring.dependency-management' version '1.1.4'
    id 'org.jetbrains.kotlin.jvm' version '1.9.22'
    id 'org.jetbrains.kotlin.plugin.spring' version '1.9.22'
}
group = 'com.apress.users'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
    maven { url 'https://repo.spring.io/snapshot' }
}
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
    implementation 'org.jetbrains.kotlin:kotlin-reflect'
    implementation 'org.webjars:bootstrap:5.2.3'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.withType(KotlinCompile) {
    kotlinOptions {
        freeCompilerArgs = ['-Xjsr305=strict']
        jvmTarget = '17'
    }
}
tasks.named('test') {
    useJUnitPlatform()
}
test {
    testLogging {
        events "passed", "skipped", "failed"
        showExceptions true
        exceptionFormat "full"
        showCauses true
        showStackTraces true
        showStandardStreams = false
    }
}

Kotlin 的 build.gradle 列表 1-9

接下来,打开 UsersApplication.kt 文件(请注意新路径:src/main/kotlin)。请参阅清单 1-10。

package com.apress.users
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class UsersApplication
fun main(args: Array) {
    runApplication(*args)
}

列表 1-10 源代码:
src/main/kotlin/com/apress/users/UsersApplication.kt

列表 1-10 展示了主要应用程序。与列表 1-3 中的 UsersApplication.java 相比,请注意仍然有一个@SpringBootApplication 注解,以及 runApplication 调用,它传递了参数(来自命令行的任何参数)和配置类,这里是 UserApplication 类本身。

接下来,添加 User.kt 文件,内容如列表 1-11 所示。

package com.apress.users
data class User(var email:String? = null, var name:String? = null)

列表 1-11 源代码:
src/main/kotlin/com/apress/users/User.kt

正如你所见,Kotlin 去除了 Java 的所有样板代码(如清单 1-4 所示)。当然,Kotlin 和 Java 各有优缺点,但我们在本书中不打算讨论这些。我建议选择你觉得更易于使用的编程语言,或者在你的组织中广泛使用的语言。

接下来,添加 UsersController.kt 文件,内容与清单 1-12 中所示相同。

package com.apress.users
import org.springframework.web.bind.annotation.*
@RestController
@RequestMapping("/users")
class UsersController {
    private val users: HashMap = object : HashMap() {
        init {
            put("ximena@email.com", User("ximena@email.com", "Ximena"))
            put("norma@email.com", User("norma@email.com", "Norma"))
        }
    }
    @GetMapping
    fun getAll(): MutableCollection = users.values
    @GetMapping("/{email}")
    fun findUserByEmail(@PathVariable email: String?): User? {
        return users[email]
    }
    @PostMapping
    fun save(@RequestBody user: User): User {
        users[user.email] = user
        return user
    }
    @DeleteMapping("/{email}")
    fun save(@PathVariable email: String?) {
        users.remove(email)
    }
}

列表 1-12 源代码路径:
src/main/kotlin/com/apress/users/UsersController.kt

UsersController.kt 类将向外界提供 API。正如你所看到的,它与 Java 版本(见清单 1-5)几乎没有区别。

使用 Kotlin 测试用户应用项目

为了测试用户应用程序项目,请将清单 1-13 中的代码添加到 UserApplicationTest.kt 文件。

package com.apress.users
import org.assertj.core.api.Assertions
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.web.client.TestRestTemplate
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class UsersApplicationTests {
    @Value("${local.server.port}")
    private val port = 0
    private val BASE_URL = "http://localhost:"
    private val USERS_PATH = "/users"
    @Autowired
    private val restTemplate: TestRestTemplate? = null
    @Test
    @Throws(Exception::class)
    fun indexPageShouldReturnHeaderOneContent() {
        Assertions.assertThat(
            restTemplate!!.getForObject(
                BASE_URL + port,
                String::class.java
            )
        ).contains("Simple Users Rest Application")
    }
    @Test
    @Throws(Exception::class)
    fun usersEndPointShouldReturnCollectionWithTwoUsers() {
        val response: MutableCollection = restTemplate!!.getForObject(
            BASE_URL + port + USERS_PATH,
            MutableCollection::class.java
        ) as MutableCollection
        Assertions.assertThat(response.size).isEqualTo(2)
    }
    @Test
    @Throws(Exception::class)
    fun userEndPointPostNewUserShouldReturnUser() {
        val user = User("dummy@email.com", "Dummy")
        val response = restTemplate!!.postForObject(
            BASE_URL + port + USERS_PATH, user,
            User::class.java
        )
        Assertions.assertThat(response).isNotNull
        Assertions.assertThat(response.email).isEqualTo(user.email)
        val users: MutableCollection = restTemplate!!.getForObject(
            BASE_URL + port + USERS_PATH,
            MutableCollection::class.java
        ) as MutableCollection
        Assertions.assertThat(users.size).isGreaterThanOrEqualTo(2)
    }
    @Test
    @Throws(Exception::class)
    fun userEndPointDeleteUserShouldReturnVoid() {
        restTemplate!!.delete("$BASE_URL$port$USERS_PATH/norma@email.com")
        val users: MutableCollection = restTemplate!!.getForObject(
            BASE_URL + port + USERS_PATH,
            MutableCollection::class.java
        ) as MutableCollection
        Assertions.assertThat(users.size).isLessThanOrEqualTo(2)
    }
    @Test
    @Throws(Exception::class)
    fun userEndPointFindUserShouldReturnUser() {
        val user = restTemplate!!.getForObject(
            "$BASE_URL$port$USERS_PATH/ximena@email.com",
            User::class.java
        )
        Assertions.assertThat(user).isNotNull
        Assertions.assertThat(user.email).isEqualTo("ximena@email.com")
    }
}

列表 1-13 源代码路径:
src/test/kotlin/com/apress/users/UsersApplicationTests.kt

UsersApplicationTests.kt 类是 UserApplicationTests.java 的 Kotlin 版本(见列表 1-8)。唯一新增的注解是 @Throws,这对于本测试来说非常直观。

现在,您可以通过右键点击此文件并选择“运行”选项来执行测试,这将产生与图 1-4 中所示类似的结果。命令行也是如此,这一点没有变化。

./gradlew test

用 Kotlin 运行用户应用程序项目

使用 Kotlin 运行 Users App 项目与使用 Java 的方式相同:可以在 IDE 中运行,也可以使用以下命令运行:

./graldew bootRun

很棒!现在你有了一个使用 Spring Boot 的不同编程语言的用户应用项目。