《Kotlin 程序设计》第八章 Kotlin 集成Spring Boot开发

第八章 Kotlin 集成Spring Boot开发

Java整个生态系统经过近20年的发展,已经非常成熟完整了。相对于年轻的Kotlin而言,我们不可能一下子抛弃整个Java生态系统。至少在目前,运行在全世界的互联网服务器上的大多数服务依然是整个Java生态的天下。

然而,在Java生态中最为出色的莫过于Spring框架体系了。尤其是近两年来,Spring Boot以及微服务的出现,使得Spring框架更加出色。

在Spring 5 中,已经增加了使用Kotlin的实现。

使用Kotlin 与 Spring Boot 开发真的是如丝般润滑。本章我们介绍使用Kotlin + Spring Boot创建一个RESTful服务,并开发一个简单的Web系统。

Step1. html页面加入头文件 相应的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 href="http://cdn.jsdelivr.net/webjars/bootstrap/3.3.4/css/bootstrap.min.css"
          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极简教程</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>

            <!--![](../../static/images/home.png)-->
        </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极简教程, 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>

重点看一下thymeleaf的语法设计风格。

写一个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默认就是使用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. 新建标准springboot resources目录

Springboot web app有很多约定,根据这些约定,可以省去一大批繁冗的配置。请看标准的工程目录结构

.
├── 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.运行测试

运行./gradlew bootRun, 启动完毕后,访问http://127.0.0.1:9891/customers.do
效果如下

螢幕快照 2017-03-11 22.23.13.png

本章节工程源码:

https://github.com/EasyKotlin/mini_springboot

参考资料

1.https://kotlinlang.org/docs/tutorials/spring-boot-restful.html


Kotlin开发者社区

专注分享 Java、 Kotlin、Spring/Spring Boot、MySQL、redis、neo4j、NoSQL、Android、JavaScript、React、Node、函数式编程、编程思想、"高可用,高性能,高实时"大型分布式系统架构设计主题。

High availability, high performance, high real-time large-scale distributed system architecture design

分布式框架:Zookeeper、分布式中间件框架等
分布式存储:GridFS、FastDFS、TFS、MemCache、redis等
分布式数据库:Cobar、tddl、Amoeba、Mycat
云计算、大数据、AI算法
虚拟化、云原生技术
分布式计算框架:MapReduce、Hadoop、Storm、Flink等
分布式通信机制:Dubbo、RPC调用、共享远程数据、消息队列等
消息队列MQ:Kafka、MetaQ,RocketMQ
怎样打造高可用系统:基于硬件、软件中间件、系统架构等一些典型方案的实现:HAProxy、基于Corosync+Pacemaker的高可用集群套件中间件系统
Mycat架构分布式演进
大数据Join背后的难题:数据、网络、内存和计算能力的矛盾和调和
Java分布式系统中的高性能难题:AIO,NIO,Netty还是自己开发框架?
高性能事件派发机制:线程池模型、Disruptor模型等等。。。

合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。不积跬步,无以至千里;不积小流,无以成江河。

Kotlin 简介

Kotlin是一门非研究性的语言,它是一门非常务实的工业级编程语言,它的使命就是帮助程序员们解决实际工程实践中的问题。使用Kotlin 让 Java程序员们的生活变得更好,Java中的那些空指针错误,浪费时间的冗长的样板代码,啰嗦的语法限制等等,在Kotlin中统统消失。Kotlin 简单务实,语法简洁而强大,安全且表达力强,极富生产力。

Java诞生于1995年,至今已有23年历史。当前最新版本是 Java 9。在 JVM 生态不断发展繁荣的过程中,也诞生了Scala、Groovy、Clojure 等兄弟语言。

Kotlin 也正是 JVM 家族中的优秀一员。Kotlin是一种现代语言(版本1.0于2016年2月发布)。它最初的目的是像Scala那样,优化Java语言的缺陷,提供更加简单实用的编程语言特性,并且解决了性能上的问题,比如编译时间。 JetBrains在这些方面做得非常出色。

Kotlin语言的特性

用 Java 开发多年以后,能够尝试一些新的东西真是太棒了。如果您是 Java 开发人员,使用 Kotlin 将会非常自然流畅。如果你是一个Swift开发者,你将会感到似曾相识,比如可空性(Nullability)。 Kotlin语言的特性有:

1.简洁

大幅减少样板代码量。

2.与Java的100%互操作性

Kotlin可以直接与Java类交互,反之亦然。这个特性使得我们可以直接重用我们的代码库,并将其迁移到 Kotlin中。由于Java的互操作性几乎无处不在。我们可以直接访问平台API以及现有的代码库,同时仍然享受和使用 Kotlin 的所有强大的现代语言功能。

3.扩展函数

Kotlin 类似于 C# 和 Gosu, 它提供了为现有类提供新功能扩展的能力,而不必从该类继承或使用任何类型的设计模式 (如装饰器模式)。

4.函数式编程

Kotlin 语言一等支持函数式编程,就像Scala一样。具备高阶函数、Lambda 表达式等函数式基本特性。

5.默认和命名参数

在Kotlin中,您可以为函数中的参数设置一个默认值,并给每个参数一个名称。这有助于编写易读的代码。

6.强大的开发工具支持

而由于是JetBrains出品,我们拥有很棒的IDE支持。虽然Java到Kotlin的自动转换并不是100% OK 的,但它确实是一个非常好的工具。使用 IDEA 的工具转换Java代码为 Kotlin 代码时,可以轻松地重用60%-70%的结果代码,而且修改成本很小。

Kotlin 除了简洁强大的语法特性外,还有实用性非常强的API以及围绕它构建的生态系统。例如:集合类 API、IO 扩展类、反射API 等。同时 Kotlin 社区也提供了丰富的文档和大量的学习资料,还有在线REPL。

A modern programming language that makes developers happier. Open source forever

图来自《Kotlin从入门到进阶实战》 (陈光剑,清华大学出版社)
图来自《Kotlin从入门到进阶实战》 (陈光剑,清华大学出版社)

https://kotlinlang.org/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容