Kotlin是一門最近比較流行的靜態型別程式語言,而且和Groovy、Scala一樣同屬Java系。Kotlin具有的很多靜態語言特性諸如:型別判斷、多正規化、擴充套件函式、模式匹配等等讓我無法只作為一個吃瓜群眾了,所以稍微花了點時間瞭解了一下該語言。
本文主要介紹一下如何使用Kotlin結合SpringBt開發一個帶有資料庫互動的REST風格基本程式
注: 本文首發於 My 公眾號 CodeSheep ,可 長按 或 掃描 下面的 小心心 來訂閱 ↓ ↓ ↓
實驗環境
- JDK不用說了,Kotlin畢竟是執行在JVM環境下的語言,所以JDK必須,我這裡用的JDK1.8
- 資料庫:MySQL
- 資料庫訪問元件:Spring data jpa
- J2EE框架:SpringBt 1.5.2.RELEASE
- 構建工具:Gradle
工程建立
沒啥好說的,我這裡建立的是基於Gradle的Kotlin工程:
建立完成後的基本工程樣式和SpringBt的工程幾乎沒任何區別,給張圖示意一下好了:
好啦,接下來我們就來寫程式碼完善這個工程即可
完善build.gradle配置
我們需要在build.gradle中引入SpringBt依賴,除此之外還要引入一些特定的外掛方便我們向寫Java程式碼一樣來寫Kotlin程式!
在dependencies中加入如下依賴:
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相關的依賴就配置上了!
接下來我們配置兩個非常關鍵的外掛依賴:
- 無參(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實踐文章在此:
- Spring Boot應用監控實戰
- SpringBoot應用部署於外接Tomcat容器
- ElasticSearch搜尋引擎在SpringBt中的實踐
- 初探Kotlin+SpringBoot聯合程式設計
- Spring Boot日誌框架實踐
- SpringBoot優雅編碼之:Lombok加持
如果有興趣,也可以抽點時間看看作者一些關於容器化、微服務化方面的文章:
- 利用K8S技術棧打造個人私有云 連載文章
- 從一份配置清單詳解Nginx伺服器配置
- Docker容器視覺化監控中心搭建
- 利用ELK搭建Docker容器化應用日誌中心
- RPC框架實踐之:Apache Thrift
- RPC框架實踐之:Google gRPC
- 微服務呼叫鏈追蹤中心搭建
- Docker容器跨主機通訊
- Docker Swarm叢集初探
- 高效編寫Dockerfile的幾條準則