使用Spring Boot和Kotlin入门Datastore

最近有段时间工作中没有写程序,所以我打算趁现在的机会,用spring-boot和kotlin自己制作一个API应用,所以我决定重新从数据存储的教程开始学习。
我正在使用由Google官方提供的交互式CUI应用的教程。
由于教程是用Java编写的,所以我在用kotlin重写它。

■ 教程

环境

macOS Big Sur 11.1
Intellij Community 2020.3
大西洋岸的苹果操作系统11.1版
Intellij社区版2020.3

教程

以下是进行教程的步骤,但只选择部分更改为Kotlin的部分。
1. 概述
2. 设置和要求(创建和设置项目)
3. 初始化云数据存储(初始化Datastore)
4. 准备新的Spring Boot Kotlin应用程序(创建Spring Boot项目)
5. 创建Book类(创建Book实体)
6. 创建BookRepository接口(创建Book实体操作的Repository)
7. 创建交互式CLI应用程序(创建Shell执行处理)
8. 运行应用程序(运行应用程序)
9. 使用Web界面查看存储在Datastore中的内容(查看存储内容)
10. 清理(清除)
11. 恭喜!

教程的更改点

4. 创建一个新的Spring Boot Java应用程序

因为想要使用Kotlin,所以从教程中的Spring Initializr(https://start.spring.io/)页面下载了以下配置。
没有特别的要求。

    • Project:Gradle Project

 

    • Language:Kotlin

 

    • Spring Boot:2.5.0

 

    • Project Metadata(Packaging):Jar

 

    Project Metadata(Java):11
Kobito.qq4G7P.png

在教程中,我们使用Maven,但由于我们用Gradle创建了项目,所以我们正在更改依赖配置。

dependencies {
    implementation("org.springframework.cloud:spring-cloud-gcp-starter-data-datastore:1.2.6.RELEASE")
    implementation("org.springframework.shell:spring-shell-starter:2.0.0.RELEASE")

    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
}

创建Book类(创建图书类)

因为教程的代码是Java,所以我将其改写为Kotlin。
代码变得更短,更易于阅读,真不错!

package app.noz.ws.example.datastore

import org.springframework.cloud.gcp.data.datastore.core.mapping.Entity
import org.springframework.data.annotation.Id

@Entity(name = "books")
class Book(@Id var id: Long? = null, var title: String, var author: String, var year: Int) {

    override fun toString(): String {
        return "Book(id=$id, title='$title', author='$author', year=$year)"
    }

}

6. 创建 BookRepository 接口(使用 Book 实体操作建立 Repository)

用Kotlin进行重写。

package app.noz.ws.example.datastore

import org.springframework.cloud.gcp.data.datastore.repository.DatastoreRepository

interface BookRepository: DatastoreRepository<Book, Long> {

    fun findByAuthor(author: String): List<Book>
    fun findByYearGreaterThan(year: Int): List<Book>
    fun findByAuthorAndYear(author: String, year: Int): List<Book>

}

7. 创建交互式的CLI应用程序(Shell执行)

用Kotlin进行重写。

package app.noz.ws.example.datastore

import com.google.common.collect.Lists
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.shell.standard.ShellComponent
import org.springframework.shell.standard.ShellMethod

@ShellComponent
@SpringBootApplication
class DatastoreApplication {

    @Autowired
    private lateinit var bookRepository: BookRepository

    @ShellMethod("Saves a book to Cloud Datastore: save-book <title> <author> <year>")
    fun saveBook(title: String, author: String, year: Int): String {
        val savedBook = this.bookRepository.save(Book(title = title, author = author, year = year))
        return savedBook.toString()
    }

    @ShellMethod("Loads all books")
    fun findAllBooks(): String {
        val books = this.bookRepository.findAll()
        return Lists.newArrayList(books).toString()
    }

    @ShellMethod("Loads books by author: find-by-author <author>")
    fun findByAuthor(author: String): String {
        val books = bookRepository.findByAuthor(author)
        return books.toString()
    }

    @ShellMethod("Loads books published after a given year: find-by-year-after <year>")
    fun findByYearAfter(year: Int): String {
        val books = bookRepository.findByYearGreaterThan(year)
        return books.toString()
    }

    @ShellMethod("Loads books by author and year: find-by-author-year <author> <year>")
    fun findByAuthorYear(author: String, year: Int): String {
        val books = bookRepository.findByAuthorAndYear(author, year)
        return books.toString()
    }

    @ShellMethod("Removes all books")
    fun removeAllBooks() {
        bookRepository.deleteAll()
    }

}

fun main(args: Array<String>) {
    runApplication<DatastoreApplication>(*args)
}

8. 运行该应用程序

Kobito.LMW6H5.png
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::       (v2.5.0-SNAPSHOT)

2021-01-16 13:47:39.282  INFO 78351 --- [           main] a.n.w.e.d.DatastoreApplicationKt         : Starting DatastoreApplicationKt using Java 14.0.1 on MacBook-Pro.local with PID 78351 (/Users/yasu/Downloads/datastore/build/classes/kotlin/main started by yasu in /Users/yasu/Downloads/datastore)
2021-01-16 13:47:39.285  INFO 78351 --- [           main] a.n.w.e.d.DatastoreApplicationKt         : No active profile set, falling back to default profiles: default
2021-01-16 13:47:40.118  INFO 78351 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Datastore repositories in DEFAULT mode.
2021-01-16 13:47:40.175  INFO 78351 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 53 ms. Found 1 Datastore repository interfaces.
2021-01-16 13:47:40.767  INFO 78351 --- [           main] o.s.c.g.a.c.GcpContextAutoConfiguration  : The default project ID is api-test-300213
2021-01-16 13:47:40.845  INFO 78351 --- [           main] o.s.c.g.core.DefaultCredentialsProvider  : Default credentials provider for service account todo-test@api-test-300213.iam.gserviceaccount.com
2021-01-16 13:47:40.846  INFO 78351 --- [           main] o.s.c.g.core.DefaultCredentialsProvider  : Scopes in use by default credentials: [https://www.googleapis.com/auth/pubsub, https://www.googleapis.com/auth/spanner.admin, https://www.googleapis.com/auth/spanner.data, https://www.googleapis.com/auth/datastore, https://www.googleapis.com/auth/sqlservice.admin, https://www.googleapis.com/auth/devstorage.read_only, https://www.googleapis.com/auth/devstorage.read_write, https://www.googleapis.com/auth/cloudruntimeconfig, https://www.googleapis.com/auth/trace.append, https://www.googleapis.com/auth/cloud-platform, https://www.googleapis.com/auth/cloud-vision, https://www.googleapis.com/auth/bigquery, https://www.googleapis.com/auth/monitoring.write]
2021-01-16 13:47:42.777  WARN 78351 --- [           main] org.jline                                : Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)
2021-01-16 13:47:42.937  INFO 78351 --- [           main] a.n.w.e.d.DatastoreApplicationKt         : Started DatastoreApplicationKt in 4.112 seconds (JVM running for 5.038)
shell:>
执行 Help 命令。
shell:>help
AVAILABLE COMMANDS

Built-In Commands
        clear: Clear the shell screen.
        exit, quit: Exit the shell.
        help: Display help about available commands.
        script: Read and execute commands from a file.
        stacktrace: Display the full stacktrace of the last error.

Datastore Application
        find-all-books: Loads all books
        find-by-author: Loads books by author: find-by-author <author>
        find-by-author-year: Loads books by author and year: find-by-author-year <author> <year>
        find-by-year-after: Loads books published after a given year: find-by-year-after <year>
        remove-all-books: Removes all books
        save-book: Saves a book to Cloud Datastore: save-book <title> <author> <year>
注册和显示

在注册了两个后,获取所有的记录。

shell:>save-book test1 author1 2021
Book(id=5644004762845184, title='test1', author='author1', year=2021)
shell:>save-book test2 author2 2021
Book(id=5632499082330112, title='test2', author='author2', year=2021)
shell:>find-all-books
[Book(id=5632499082330112, title='test2', author='author2', year=2021), Book(id=5644004762845184, title='test1', author='author1', year=2021)]

9. 通过Web界面查看Datastore中存储的内容。

Kobito.0q51nT.png

10. 清理

删除后,通过命令和网页进行确认,数据确实被删除了。

shell:>remove-all-books
shell:>find-all-books
[]
Kobito.lbj2IN.png

当使用Gradle命令执行时出现故障。

如果使用Gradle命令执行” ./gradlew bootRun “,则始终会输出”EXECUTING [16s]”,交互性命令无法正常工作。虽然可执行,但显示结果非常混乱。如果有人知道原因,请告诉我,谢谢 m(_ _)m

% ./gradlew bootRun

> Task :bootRun

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::       (v2.5.0-SNAPSHOT)

2021-01-16 13:56:59.649  INFO 78536 --- [           main] a.n.w.e.d.DatastoreApplicationKt         : Starting DatastoreApplicationKt using Java 14.0.1 on MacBook-Pro.local with PID 78536 (/Users/yasu/Downloads/datastore/build/classes/kotlin/main started by yasu in /Users/yasu/Downloads/datastore)
2021-01-16 13:56:59.651  INFO 78536 --- [           main] a.n.w.e.d.DatastoreApplicationKt         : No active profile set, falling back to default profiles: default
2021-01-16 13:57:00.140  INFO 78536 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Datastore repositories in DEFAULT mode.
2021-01-16 13:57:00.184  INFO 78536 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 39 ms. Found 1 Datastore repository interfaces.
2021-01-16 13:57:00.587  INFO 78536 --- [           main] o.s.c.g.a.c.GcpContextAutoConfiguration  : The default project ID is api-test-300213
2021-01-16 13:57:00.632  INFO 78536 --- [           main] o.s.c.g.core.DefaultCredentialsProvider  : Default credentials provider for service account todo-test@api-test-300213.iam.gserviceaccount.com
2021-01-16 13:57:00.632  INFO 78536 --- [           main] o.s.c.g.core.DefaultCredentialsProvider  : Scopes in use by default credentials: [https://www.googleapis.com/auth/pubsub, https://www.googleapis.com/auth/spanner.admin, https://www.googleapis.com/auth/spanner.data, https://www.googleapis.com/auth/datastore, https://www.googleapis.com/auth/sqlservice.admin, https://www.googleapis.com/auth/devstorage.read_only, https://www.googleapis.com/auth/devstorage.read_write, https://www.googleapis.com/auth/cloudruntimeconfig, https://www.googleapis.com/auth/trace.append, https://www.googleapis.com/auth/cloud-platform, https://www.googleapis.com/auth/cloud-vision, https://www.googleapis.com/auth/bigquery, https://www.googleapis.com/auth/monitoring.write]
2021-01-16 13:57:02.198  WARN 78536 --- [           main] org.jline                                : Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)
2021-01-16 13:57:02.311  INFO 78536 --- [           main] a.n.w.e.d.DatastoreApplicationKt         : Started DatastoreApplicationKt in 3.019 seconds (JVM running for 3.525)
shell:>Run
<==========---> 83% EXECUTING [16s] ← これ!!?
> :bootRun

最终

我通过教程进行实践,发现比我想象中更简单,但是由于 Kotlin 对于初学者来说太过陌生,所以花费的时间比预期的多。我打算使用 spring-boot/kotlin/datastore 来制作 API,并且如果有余力的话,我还想在 Qiita 上发布。

这段代码并不是很重要,但是我还是会将源代码上传到 GitHub 上。
https://github.com/ynozue/DatasotreSample_kotlin