初探Kotlin+SpringBoot聯合編程

Kotlin是一門最近比較流行的靜態類型編程語言,並且和Groovy、Scala同樣同屬Java系。Kotlin具備的不少靜態語言特性諸如:類型判斷、多範式、擴展函數、模式匹配等等讓我沒法只做爲一個吃瓜羣衆了,因此稍微花了點時間瞭解了一下該語言。java

本文主要介紹一下如何使用Kotlin結合SpringBt開發一個帶有數據庫交互的REST風格基本程序mysql

注: 本文首發於 My 公衆號 CodeSheep ,可 長按掃描 下面的 當心心 來訂閱 ↓ ↓ ↓web

CodeSheep · 程序羊


實驗環境

  • JDK不用說了,Kotlin畢竟是運行在JVM環境下的語言,因此JDK必須,我這裏用的JDK1.8
  • 數據庫:MySQL
  • 數據庫訪問組件:Spring data jpa
  • J2EE框架:SpringBt 1.5.2.RELEASE
  • 構建工具:Gradle

工程建立

沒啥好說的,我這裏建立的是基於Gradle的Kotlin工程:spring

基於Gradle的Kotlin工程

建立完成後的基本工程樣式和SpringBt的工程幾乎沒任何區別,給張圖示意一下好了:sql

工程基本樣式

好啦,接下來咱們就來寫代碼完善這個工程便可數據庫


完善build.gradle配置

咱們須要在build.gradle中引入SpringBt依賴,除此以外還要引入一些特定的插件方便咱們向寫Java代碼同樣來寫Kotlin程序!編程

在dependencies中加入以下依賴:c#

dependencies {
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
    testCompile group: 'junit', name: 'junit', version: '4.12'
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("org.springframework.boot:spring-boot-starter-test")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile('mysql:mysql-connector-java:5.1.13')
}
複製代碼

這樣SpringBt相關的依賴就配置上了!springboot

接下來咱們配置兩個很是關鍵的插件依賴:bash

  • 無參(no-arg)插件
  • 全開放(allopen)插件

咱們先配上,等下解釋:

buildscript {
    ext.kotlin_version = '1.1.1'
    ext.springboot_version = '1.5.2.RELEASE'

    repositories {
        mavenCentral()
    }
    dependencies {
        // Kotlin Gradle插件
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        // SpringBoot Gradle插件
        classpath("org.springframework.boot:spring-boot-gradle-plugin:$springboot_version")
        // Kotlin整合SpringBoot的默認無參構造函數,默認把全部的類設置open類插件
        classpath("org.jetbrains.kotlin:kotlin-noarg:$kotlin_version") // 無參插件
        classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlin_version") // 全開放插件
    }
}
複製代碼

其中(如下解釋源自《Kotlin極簡教程》):

  • org.jetbrains.kotlin:kotlin-noarg是無參(no-arg)編譯器插件,它爲具備特定註解的類生成一個額外的零參數構造函數。 這個生成的構造函數是合成的,所以不能從 Java 或 Kotlin 中直接調用,但可使用反射調用。 這樣咱們就可使用 Java Persistence API(JPA)實例化 data 類。

  • org.jetbrains.kotlin:kotlin-allopen 是全開放編譯器插件。咱們使用Kotlin 調用Java的Spring AOP框架和庫,須要類爲 open(可被繼承實現),而Kotlin 類和函數都是默認 final 的,這樣咱們須要爲每一個類和函數前面加上open修飾符。這樣的代碼寫起來很費事。還好,咱們有all-open 編譯器插件。它會適配 Kotlin 以知足這些框架的需求,並使用指定的註解標註類而其成員無需顯式使用 open 關鍵字打開。 例如,當咱們使用 Spring 時,就不須要打開全部的類,跟咱們在Java中寫代碼同樣,只須要用相應的註解標註便可,如 @Configuration 或 @Service。

講白了,引入這兩個特定的插件的目的就是爲了方便咱們向寫SpringBt代碼同樣來寫Kotlin程序!


配置application.properties

這裏面主要是跟Mysql數據庫相關的一些配置:

spring.datasource.url = jdbc:mysql://localhost:3306/easykotlin
spring.datasource.username = root
spring.datasource.password = 你的Mysql密碼
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.database = MYSQL
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

server.port=7000
複製代碼

正式編寫工程

咱們須要去數據庫中查詢東西,因此二話不說,寫個訪問數據庫的標準代碼層:

  • controller
  • entity
  • repository
  • service

總體代碼框架

各部分代碼以下:

  • People.kt
@Entity
class People(
        @Id @GeneratedValue(strategy = GenerationType.AUTO)
        val id: Long?,
        val firstName: String?,
        val lastName: String?,
        val gender: String?,
        val age: Int?,
        val gmtCreated: Date,
        val gmtModified: Date
) {
    override fun toString(): String {
        return "People(id=$id, firstName='$firstName', lastName='$lastName', gender='$gender', age=$age, gmtCreated=$gmtCreated, gmtModified=$gmtModified)"
    }
}
複製代碼
  • PeopleRepository.kt
interface PeopleRepository : CrudRepository<People, Long> {
    fun findByLastName(lastName: String): List<People>?
}
複製代碼
  • PeopleService.kt
@Service
class PeopleService : PeopleRepository {

    @Autowired
    val peopleRepository: PeopleRepository? = null

    override fun findByLastName(lastName: String): List<People>? {
        return peopleRepository?.findByLastName(lastName)
    }

    override fun <S : People?> save(entity: S): S? {
        return peopleRepository?.save(entity)
    }

    override fun <S : People?> save(entities: MutableIterable<S>?): MutableIterable<S>? {
        return peopleRepository?.save(entities)
    }

    override fun delete(entities: MutableIterable<People>?) {
    }

    override fun delete(entity: People?) {
    }

    override fun delete(id: Long?) {
    }

    override fun findAll(ids: MutableIterable<Long>?): MutableIterable<People>? {
        return peopleRepository?.findAll(ids)
    }

    override fun findAll(): MutableIterable<People>? {
        return peopleRepository?.findAll()
    }

    override fun exists(id: Long?): Boolean {
        return peopleRepository?.exists(id)!!
    }

    override fun count(): Long {
        return peopleRepository?.count()!!
    }

    override fun findOne(id: Long?): People? {
        return peopleRepository?.findOne(id)
    }

    override fun deleteAll() {
    }
}
複製代碼
  • PeopleController.kt
@Controller
class PeopleController {
    @Autowired
    val peopleService: PeopleService? = null

    @GetMapping(value = "/hello")
    @ResponseBody
    fun hello(@RequestParam(value = "lastName") lastName: String): Any {
        val peoples = peopleService?.findByLastName(lastName)
        val map = HashMap<Any, Any>()
        map.put("hello", peoples!!)
        return map
    }
}
複製代碼

可見有了無參、全開放組件加持後,寫代碼和寫Java的代碼基本沒區別了


實際實驗

首先須要去Mysql中建好數據庫,並插入一些數據:

數據庫預覽

而後啓動工程,訪問: http://localhost:7000/hello?lastName=wang

能夠看到數據成功被取回:

成功獲取到數據


參考文獻

《Kotlin極簡教程》


後記

做者更多的SpringBt實踐文章在此:


若是有興趣,也能夠抽點時間看看做者一些關於容器化、微服務化方面的文章:


CodeSheep · 程序羊
相關文章
相關標籤/搜索