第八章 Kotlin 集成Spring Boot開發(fā)
Java整個(gè)生態(tài)系統(tǒng)經(jīng)過近20年的發(fā)展,已經(jīng)非常成熟完整了。相對(duì)于年輕的Kotlin而言,我們不可能一下子拋棄整個(gè)Java生態(tài)系統(tǒng)。至少在目前,運(yùn)行在全世界的互聯(lián)網(wǎng)服務(wù)器上的大多數(shù)服務(wù)依然是整個(gè)Java生態(tài)的天下。
然而,在Java生態(tài)中最為出色的莫過于Spring框架體系了。尤其是近兩年來,Spring Boot以及微服務(wù)的出現(xiàn),使得Spring框架更加出色。
在Spring 5 中,已經(jīng)增加了使用Kotlin的實(shí)現(xiàn)。
使用Kotlin 與 Spring Boot 開發(fā)真的是如絲般潤(rùn)滑。本章我們介紹使用Kotlin + Spring Boot創(chuàng)建一個(gè)RESTful服務(wù),并開發(fā)一個(gè)簡(jiǎn)單的Web系統(tǒng)。
Step1. html頁面加入頭文件 相應(yīng)的schema
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
Step2.主頁面模板
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<th:block th:include="common/header :: head"></th:block>
<body>
<th:block th:include="common/header :: header"></th:block>
<div th:if="${not #lists.isEmpty(customers)}">
<h2>Customer List</h2>
<table id="customersTable" class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>FirstName</th>
<th>LastName</th>
<th>Created Time</th>
</tr>
</thead>
<tbody>
<tr th:each="customer : ${customers}">
<td th:text="${customer.id}"><a href="/product/${product.id}">Id</a></td>
<td th:text="${customer.firstName}">FirstName</td>
<td th:text="${customer.lastName}">LastName</td>
<td th:text="${customer.gmtCreated}">gmtCreated</td>
<!--<td><a th:href="${ '/product/' + product.id}">View</a></td>-->
<!--<td><a th:href="${'/product/edit/' + product.id}">Edit</a></td>-->
</tr>
</tbody>
</table>
</div>
<th:block th:include="common/footer :: footer"></th:block>
</body>
</html>
Step3.include common模板說明
common/header.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en" th:fragment="head">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link
th:href="@{/webjars/bootstrap/3.3.4/css/bootstrap.min.css}"
rel="stylesheet" media="screen"/>
<link href="../../static/css/jquery.dataTables.min.css"
th:href="@{css/jquery.dataTables.min.css}" rel="stylesheet" media="screen"/>
<link href="../../static/css/mini_springboot.css"
th:href="@{css/mini_springboot.css}" rel="stylesheet" media="screen"/>
<title>Mini SpringBoot Tutorial</title>
</head>
<body>
<div th:fragment="header">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#" th:href="@{/}">Home</a>
<ul class="nav navbar-nav">
<li><a href="#" th:href="@{/customers.do}">Customers</a></li>
<li><a href="#" th:href="@{/customer/new}">Create Customer</a></li>
</ul>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="row text-center">
<div class="">
<h1 class="center">Springboot極簡(jiǎn)教程</h1>
<h2>Mini SpringBoot Tutorial</h2>
<h3>Spring Boot Kotlin Thymeleaf Web App</h3>
</div>
</div>
<div class="row text-center">
<iframe class="iframe" src="https://jason-chen-2017.github.io/Jason-Chen-2017/"></iframe>
<!---->
</div>
</div>
</div>
</body>
</html>
common/footer.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<div th:fragment="footer">
<div class="footer">Springboot極簡(jiǎn)教程, Jason Chen, 2017</div>
<script src="http://cdn.jsdelivr.net/webjars/jquery/2.1.4/jquery.min.js"
th:src="@{/webjars/jquery/2.1.4/jquery.min.js}"></script>
<script src="http://cdn.jsdelivr.net/webjars/bootstrap/3.3.4/js/bootstrap.min.js"
th:src="@{/webjars/bootstrap/3.3.4/js/bootstrap.min.js}"></script>
<script src="../../static/js/jquery.dataTables.min.js"
th:src="@{js/jquery.dataTables.min.js}"></script>
<script src="../../static/js/mini_springboot.js" th:src="@{js/mini_springboot.js}"></script>
</div>
</body>
</html>
重點(diǎn)看一下thymeleaf的語法設(shè)計(jì)風(fēng)格。
寫一個(gè)th:fragment="{id}"
<div th:fragment="footer">
。。。
</div>
可以直接在其他頁面 th:include
<th:block th:include="common/footer :: footer"></th:block>
<h5>Step4. 配置build.gradle,添加spring-boot-starter-thymeleaf
Spring Boot默認(rèn)就是使用thymeleaf模板引擎的,所以只需要在build.gradle(pom.xml)加入依賴即可。
version = "0.0.1-SNAPSHOT"
buildscript {
ext {
springBootVersion = "1.5.2.RELEASE"
kotlinVersion = "1.1.0"
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
classpath("org.jetbrains.kotlin:kotlin-noarg:$kotlinVersion")
classpath("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
}
}
apply {
plugin("kotlin")
plugin("kotlin-spring")
plugin("kotlin-jpa")
plugin("org.springframework.boot")
plugin 'java'
plugin 'eclipse'
plugin 'idea'
// plugin: 'spring-boot'
}
repositories {
mavenCentral()
}
jar {
baseName = 'mini_springboot'
version = '0.0.1'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("org.springframework.boot:spring-boot-starter-data-jpa")
// compile("com.h2database:h2")
compile("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
compile("org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion")
compile("com.fasterxml.jackson.module:jackson-module-kotlin:2.8.4")
testCompile("org.springframework.boot:spring-boot-starter-test")
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile("org.springframework.boot:spring-boot-starter-jetty")
compile("org.springframework.boot:spring-boot-starter-actuator")
compile('mysql:mysql-connector-java:5.1.13')
testCompile("junit:junit")
//thymeleaf
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
//WebJars
compile("org.webjars:bootstrap:3.3.4")
compile("org.webjars:jquery:2.1.4")
// https://mvnrepository.com/artifact/org.webjars/datatables
compile group: 'org.webjars', name: 'datatables', version: '1.10.13'
}
Step5. 新建標(biāo)準(zhǔn)springboot resources目錄
Springboot web app有很多約定,根據(jù)這些約定,可以省去一大批繁冗的配置。請(qǐng)看標(biāo)準(zhǔn)的工程目錄結(jié)構(gòu)
.
├── META-INF
│ └── MANIFEST.MF
├── README.md
├── README_.md
├── build
│ └── kotlin-build
│ └── caches
│ └── version.txt
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── run.bat
├── run.sh
├── settings.gradle
└── src
├── main
│ ├── java
│ ├── kotlin
│ │ └── jason
│ │ └── chen
│ │ └── mini_springboot
│ │ ├── console
│ │ │ └── HelloWorld.kt
│ │ └── restful
│ │ ├── Application.kt
│ │ ├── biz
│ │ │ └── CustomerService.kt
│ │ ├── controller
│ │ │ └── CustomerController.kt
│ │ ├── entity
│ │ │ └── Customer.kt
│ │ └── utils
│ │ └── DateUtils.kt
│ └── resources
│ ├── application.properties
│ ├── application.yml
│ ├── static
│ │ ├── css
│ │ │ ├── jquery.dataTables.min.css
│ │ │ └── mini_springboot.css
│ │ ├── images
│ │ │ ├── home.png
│ │ │ ├── sort_asc.png
│ │ │ ├── sort_both.png
│ │ │ └── sort_desc.png
│ │ └── js
│ │ ├── jquery.dataTables.min.js
│ │ └── mini_springboot.js
│ └── templates
│ ├── common
│ │ ├── footer.html
│ │ └── header.html
│ ├── customers.html
│ ├── index.html
│ ├── productform.html
│ ├── products.html
│ └── productshow.html
└── test
├── java
├── kotlin
└── resources
30 directories, 35 files
Step5. 寫Controller
package jason.chen.mini_springboot.restful.controller
import jason.chen.mini_springboot.restful.biz.CustomerService
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.ResponseBody
@Controller
class CustomerController(val customerService: CustomerService) {
@GetMapping(value = "/")
fun index(): String {
return "index"
}
@GetMapping("/customers.do")
fun listAll(model: Model): String {
val allCustomers = customerService.findAll()
model.addAttribute("customers", allCustomers)
return "customers"
}
@GetMapping("/listCustomers")
@ResponseBody
fun listCustomers(model: Model) = customerService.findAll()
@GetMapping("/{lastName}")
@ResponseBody
fun findByLastName(@PathVariable lastName: String)
= customerService.findByLastName(lastName)
}
Step6.運(yùn)行測(cè)試
運(yùn)行./gradlew bootRun, 啟動(dòng)完畢后,訪問http://127.0.0.1:9891/customers.do
效果如下

本章節(jié)工程源碼:
https://github.com/EasyKotlin/mini_springboot
參考資料
1.https://kotlinlang.org/docs/tutorials/spring-boot-restful.html
Kotlin開發(fā)者社區(qū)

專注分享 Java、 Kotlin、Spring/Spring Boot、MySQL、redis、neo4j、NoSQL、Android、JavaScript、React、Node、函數(shù)式編程、編程思想、"高可用,高性能,高實(shí)時(shí)"大型分布式系統(tǒng)架構(gòu)設(shè)計(jì)主題。
High availability, high performance, high real-time large-scale distributed system architecture design。
分布式框架:Zookeeper、分布式中間件框架等
分布式存儲(chǔ):GridFS、FastDFS、TFS、MemCache、redis等
分布式數(shù)據(jù)庫:Cobar、tddl、Amoeba、Mycat
云計(jì)算、大數(shù)據(jù)、AI算法
虛擬化、云原生技術(shù)
分布式計(jì)算框架:MapReduce、Hadoop、Storm、Flink等
分布式通信機(jī)制:Dubbo、RPC調(diào)用、共享遠(yuǎn)程數(shù)據(jù)、消息隊(duì)列等
消息隊(duì)列MQ:Kafka、MetaQ,RocketMQ
怎樣打造高可用系統(tǒng):基于硬件、軟件中間件、系統(tǒng)架構(gòu)等一些典型方案的實(shí)現(xiàn):HAProxy、基于Corosync+Pacemaker的高可用集群套件中間件系統(tǒng)
Mycat架構(gòu)分布式演進(jìn)
大數(shù)據(jù)Join背后的難題:數(shù)據(jù)、網(wǎng)絡(luò)、內(nèi)存和計(jì)算能力的矛盾和調(diào)和
Java分布式系統(tǒng)中的高性能難題:AIO,NIO,Netty還是自己開發(fā)框架?
高性能事件派發(fā)機(jī)制:線程池模型、Disruptor模型等等。。。
合抱之木,生于毫末;九層之臺(tái),起于壘土;千里之行,始于足下。不積跬步,無以至千里;不積小流,無以成江河。

Kotlin 簡(jiǎn)介
Kotlin是一門非研究性的語言,它是一門非常務(wù)實(shí)的工業(yè)級(jí)編程語言,它的使命就是幫助程序員們解決實(shí)際工程實(shí)踐中的問題。使用Kotlin 讓 Java程序員們的生活變得更好,Java中的那些空指針錯(cuò)誤,浪費(fèi)時(shí)間的冗長(zhǎng)的樣板代碼,啰嗦的語法限制等等,在Kotlin中統(tǒng)統(tǒng)消失。Kotlin 簡(jiǎn)單務(wù)實(shí),語法簡(jiǎn)潔而強(qiáng)大,安全且表達(dá)力強(qiáng),極富生產(chǎn)力。
Java誕生于1995年,至今已有23年歷史。當(dāng)前最新版本是 Java 9。在 JVM 生態(tài)不斷發(fā)展繁榮的過程中,也誕生了Scala、Groovy、Clojure 等兄弟語言。
Kotlin 也正是 JVM 家族中的優(yōu)秀一員。Kotlin是一種現(xiàn)代語言(版本1.0于2016年2月發(fā)布)。它最初的目的是像Scala那樣,優(yōu)化Java語言的缺陷,提供更加簡(jiǎn)單實(shí)用的編程語言特性,并且解決了性能上的問題,比如編譯時(shí)間。 JetBrains在這些方面做得非常出色。
Kotlin語言的特性
用 Java 開發(fā)多年以后,能夠嘗試一些新的東西真是太棒了。如果您是 Java 開發(fā)人員,使用 Kotlin 將會(huì)非常自然流暢。如果你是一個(gè)Swift開發(fā)者,你將會(huì)感到似曾相識(shí),比如可空性(Nullability)。 Kotlin語言的特性有:
1.簡(jiǎn)潔
大幅減少樣板代碼量。
2.與Java的100%互操作性
Kotlin可以直接與Java類交互,反之亦然。這個(gè)特性使得我們可以直接重用我們的代碼庫,并將其遷移到 Kotlin中。由于Java的互操作性幾乎無處不在。我們可以直接訪問平臺(tái)API以及現(xiàn)有的代碼庫,同時(shí)仍然享受和使用 Kotlin 的所有強(qiáng)大的現(xiàn)代語言功能。
3.擴(kuò)展函數(shù)
Kotlin 類似于 C# 和 Gosu, 它提供了為現(xiàn)有類提供新功能擴(kuò)展的能力,而不必從該類繼承或使用任何類型的設(shè)計(jì)模式 (如裝飾器模式)。
4.函數(shù)式編程
Kotlin 語言一等支持函數(shù)式編程,就像Scala一樣。具備高階函數(shù)、Lambda 表達(dá)式等函數(shù)式基本特性。
5.默認(rèn)和命名參數(shù)
在Kotlin中,您可以為函數(shù)中的參數(shù)設(shè)置一個(gè)默認(rèn)值,并給每個(gè)參數(shù)一個(gè)名稱。這有助于編寫易讀的代碼。
6.強(qiáng)大的開發(fā)工具支持
而由于是JetBrains出品,我們擁有很棒的IDE支持。雖然Java到Kotlin的自動(dòng)轉(zhuǎn)換并不是100% OK 的,但它確實(shí)是一個(gè)非常好的工具。使用 IDEA 的工具轉(zhuǎn)換Java代碼為 Kotlin 代碼時(shí),可以輕松地重用60%-70%的結(jié)果代碼,而且修改成本很小。
Kotlin 除了簡(jiǎn)潔強(qiáng)大的語法特性外,還有實(shí)用性非常強(qiáng)的API以及圍繞它構(gòu)建的生態(tài)系統(tǒng)。例如:集合類 API、IO 擴(kuò)展類、反射API 等。同時(shí) Kotlin 社區(qū)也提供了豐富的文檔和大量的學(xué)習(xí)資料,還有在線REPL。
A modern programming language that makes developers happier. Open source forever


