摘要:框架官方支持的框架,風(fēng)格頗為類似,并且充分發(fā)揮了的強(qiáng)類型優(yōu)勢(shì)。這是一個(gè)主要面向的框架,為提供了一些額外特性。依賴注入框架用法簡(jiǎn)單,支持等特性。
首先要說明,Kotlin支持你所知道的所有Java框架和庫,包括但不限于Spring全家桶、Guice、Hibernate、MyBatis、Jackson等,甚至有人在用Kotlin寫Spark大數(shù)據(jù)程序,因此Kotlin不需要專門的框架。因此,為Kotlin開發(fā)框架的人,都是懷著滿滿的愛!
Kotlin現(xiàn)在主要流行于Android開發(fā),我是搞后端開發(fā)的,不熟悉Android,就不妄言了。這篇文章主要介紹后端框架,包括Web、SQL、依賴注入、測(cè)試這些方面。
Web框架 Wasabi- An HTTP Framework?https://github.com/wasabifx/wasabi
極簡(jiǎn)的Web框架,基于Netty構(gòu)建,編程風(fēng)格效仿了Ruby的Sinatra和Node.js的Express。
Java也有個(gè)效仿Sinatra風(fēng)格的Web框架,叫Spark(是的,與某大數(shù)據(jù)框架重名了)。
使用很簡(jiǎn)單:
var server = AppServer() server.get("/", { response.send("Hello World!") }) server.start()
也可以這么寫:
server.get(“/“) { response.send("Hello World!") }
加一個(gè)前置攔截器(next()表示進(jìn)入下一步處理):
server.get("/", { val log = Log() log.info("URI requested is ${request.uri}") next() }, { response.send("Hello World!", "application/json") } )
獲取參數(shù):
server.get("/customer/:id", { val customerId = request.routeParams["id"] } )
server.get("/customer", { val customerName = request.queryParams["name"] } )
為了提供可維護(hù)性,可以在別處定義一個(gè)方法,在程序入口引用它:
appServer.get("/customer", ::getCustomer)
這種微框架很適合快速為一個(gè)后端服務(wù)添加REST接口。
Karahttps://github.com/TinyMissio...
JetBrains官方支持的Web框架,特色是類型安全的HTML DSL和CSS DSL (風(fēng)格類似Haml/Slim和SASS/LESS)
因?yàn)镵otlin是支持動(dòng)態(tài)執(zhí)行代碼的,所以DSL理論上是可以熱修改的,但是不知道Kara框架有沒有內(nèi)置這個(gè)特性。
DSL示例HTML View:
class Index() : HtmlView() { override fun render(context: ActionContext) { h2("Welcome to Kara") p("Your app is up and running, now it"s time to make something!") p("Start by editing this file here: src/com/karaexample/views/home/Index.kt") } }
HTML Layout:
class DefaultLayout() : HtmlLayout() { override fun render(context: ActionContext, mainView: HtmlView) { head { title("Kara Demo Title") stylesheet(DefaultStyles()) } body { h1("Kara Demo Site") div(id="main") { renderView(context, mainView) } a(text="Kara is developed by Tiny Mission", ) } } }
Forms:
class BookForm(val book : Book) : HtmlView() { override fun render(context: ActionContext) { h2("Book Form") formFor(book, "/updatebook", FormMethod.Post) { p { labelFor("title") textFieldFor("title") } p { labelFor("isPublished", "Is Published?") checkBoxFor("isPublished") } } } }
CSS:
class DefaultStyles() : Stylesheet() { override fun render() { s("body") { backgroundColor = c("#f0f0f0") } s("#main") { width = 85.percent backgroundColor = c("#fff") margin = box(0.px, auto) padding = box(1.em) border = "1px solid #ccc" borderRadius = 5.px } s("input[type=text], textarea") { padding = box(4.px) width = 300.px } s("textarea") { height = 80.px } s("table.fields") { s("td") { padding = box(6.px, 3.px) } s("td.label") { textAlign = TextAlign.right } s("td.label.top") { verticalAlign = VerticalAlign.top } } } }
其實(shí)就是在寫Kotlin代碼,顯然你可以自行擴(kuò)展出更多的DSL,還可以用面向?qū)ο蠡蚝瘮?shù)式的方式來復(fù)用。
Controllers 像Spring MVC和Django的風(fēng)格不需要用到反射,性能更高:
object Home { val layout = DefaultLayout() Get("/") class Index() : Request({ karademo.views.home.Index() }) Get("/test") class Test() : Request({ TextResult("This is a test action, yo") }) Post("/updatebook") class Update() : Request({ redirect("/forms") }) Get("/complex/*/list/:id") Complex(id : Int) : Request({ TextResult("complex: ${params[0]} id = ${params["id"]}") }) }當(dāng)然也有攔截器,在這里叫Middleware
實(shí)現(xiàn)這個(gè)接口并綁定到路由路徑就可以了:
/** * Base class for Kara middleware. * Middleware is code that is injected inside the request pipeline, * either before or after a request is handled by the application. */ abstract class Middleware() { /** * Gets called before the application is allowed to handle the request. * Return false to stop the request pipeline from executing anything else. */ abstract fun beforeRequest(context : ActionContext) : Boolean /** * Gets called after the application is allowed to handle the request. * Return false to stop the request pipeline from executing anything else. */ abstract fun afterRequest(context : ActionContext) : Boolean }
appConfig.middleware.add(MyMiddleware(), "/books")
綜合來說,Kara確實(shí)是比較優(yōu)秀的web框架。
但有一點(diǎn)不好,默認(rèn)使用3000端口,與Rails重復(fù)了。
SQL框架 Exposedhttps://github.com/jetbrains/...
JetBrains官方支持的SQL/ORM框架,風(fēng)格頗為類似Django ORM,并且充分發(fā)揮了Kotlin的強(qiáng)類型優(yōu)勢(shì)。
項(xiàng)目主頁有很長一段示例代碼,全程都是強(qiáng)類型,非常流暢,令人賞心悅目:
import org.jetbrains.exposed.sql.* import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.SchemaUtils.create import org.jetbrains.exposed.sql.SchemaUtils.drop object Users : Table() { val id = varchar("id", 10).primaryKey() // Columnval name = varchar("name", length = 50) // Column val cityId = (integer("city_id") references Cities.id).nullable() // Column } object Cities : Table() { val id = integer("id").autoIncrement().primaryKey() // Column val name = varchar("name", 50) // Column } fun main(args: Array ) { Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") transaction { create (Cities, Users) val saintPetersburgId = Cities.insert { it[name] = "St. Petersburg" } get Cities.id val munichId = Cities.insert { it[name] = "Munich" } get Cities.id Cities.insert { it[name] = "Prague" } Users.insert { it[id] = "andrey" it[name] = "Andrey" it[cityId] = saintPetersburgId } Users.insert { it[id] = "sergey" it[name] = "Sergey" it[cityId] = munichId } Users.insert { it[id] = "eugene" it[name] = "Eugene" it[cityId] = munichId } Users.insert { it[id] = "alex" it[name] = "Alex" it[cityId] = null } Users.insert { it[id] = "smth" it[name] = "Something" it[cityId] = null } Users.update({Users.id eq "alex"}) { it[name] = "Alexey" } Users.deleteWhere{Users.name like "%thing"} println("All cities:") for (city in Cities.selectAll()) { println("${city[Cities.id]}: ${city[Cities.name]}") } println("Manual join:") (Users innerJoin Cities).slice(Users.name, Cities.name). select {(Users.id.eq("andrey") or Users.name.eq("Sergey")) and Users.id.eq("sergey") and Users.cityId.eq(Cities.id)}.forEach { println("${it[Users.name]} lives in ${it[Cities.name]}") } println("Join with foreign key:") (Users innerJoin Cities).slice(Users.name, Users.cityId, Cities.name). select {Cities.name.eq("St. Petersburg") or Users.cityId.isNull()}.forEach { if (it[Users.cityId] != null) { println("${it[Users.name]} lives in ${it[Cities.name]}") } else { println("${it[Users.name]} lives nowhere") } } println("Functions and group by:") ((Cities innerJoin Users).slice(Cities.name, Users.id.count()).selectAll().groupBy(Cities.name)).forEach { val cityName = it[Cities.name] val userCount = it[Users.id.count()] if (userCount > 0) { println("$userCount user(s) live(s) in $cityName") } else { println("Nobody lives in $cityName") } } drop (Users, Cities) } }
CRUD和各種查詢都很容易表達(dá),也能自動(dòng)建表,確實(shí)方便得很。
但是文檔沒提到schema migration,想必是沒這個(gè)功能。如果你想修改表結(jié)構(gòu),還得手動(dòng)用SQL去改?這方面需要提高。
Requeryhttps://github.com/requery/re...
這是一個(gè)主要面向Android的Java ORM框架,為Kotlin提供了一些額外特性。
你需要把實(shí)體聲明為abstract class或interface,然后標(biāo)上類似JPA的注解:
@Entity abstract class AbstractPerson { @Key @Generated int id; @Index("name_index") // table specification String name; @OneToMany // relationships 1:1, 1:many, many to many SetphoneNumbers; @Converter(EmailToStringConverter.class) // custom type conversion Email email; @PostLoad // lifecycle callbacks void afterLoad() { updatePeopleList(); } // getter, setters, equals & hashCode automatically generated into Person.java }
@Entity public interface Person { @Key @Generated int getId(); String getName(); @OneToMany SetgetPhoneNumbers(); String getEmail(); }
它提供了SQL DSL,看起來似乎依賴代碼生成:
Resultquery = data .select(Person.class) .where(Person.NAME.lower().like("b%")).and(Person.AGE.gt(20)) .orderBy(Person.AGE.desc()) .limit(5) .get();
用Kotlin可以寫得更簡(jiǎn)潔:
data { val result = select(Person::class) where (Person::age gt 21) and (Person::name eq "Bob") limit 10 }Kwery, Kuery, Kotliquery
https://github.com/andrewoma/...
https://github.com/x2bool/kuery
https://github.com/seratch/ko...
這三個(gè)實(shí)際上是SQL庫,對(duì)JDBC做了一些封裝,提供了簡(jiǎn)易的SQL DSL。我不想用篇幅來介紹,有興趣的朋友可以去項(xiàng)目主頁看一看。
還要特別推薦Ebean ORM框架 https://ebean-orm.github.io/ 融合了JPA和Active Record的風(fēng)格,成熟度相對(duì)高一些,已有一定規(guī)模的用戶群,雖然不是專為Kotlin設(shè)計(jì),但作者也在使用Kotlin。
依賴注入框架 Kodeinhttps://github.com/SalomonBry...
用法簡(jiǎn)單,支持scopes, modules, lazy等特性。
val kodein = Kodein { bind() with provider { RandomDice(0, 5) } bind () with singleton { SqliteDS.open("path/to/file") } } class Controller(private val kodein: Kodein) { private val ds: DataSource = kodein.instance() }
個(gè)人認(rèn)為Kodein沒有什么亮點(diǎn)。
因?yàn)閭鹘y(tǒng)的Spring和Guice都是可以用的,功能和穩(wěn)定性更有保證,所以建議繼續(xù)用傳統(tǒng)的吧。
測(cè)試框架 Spekhttps://github.com/JetBrains/...
JetBrains官方支持的規(guī)格測(cè)試框架,效仿了Ruby的RSpec,代碼風(fēng)格很相似,可讀性很好:
class SimpleTest : Spek({ describe("a calculator") { val calculator = SampleCalculator() it("should return the result of adding the first number to the second number") { val sum = calculator.sum(2, 4) assertEquals(6, sum) } it("should return the result of subtracting the second number from the first number") { val subtract = calculator.subtract(4, 2) assertEquals(2, subtract) } } })
除此之外,Java的JUnit, TestNG, Mockito等框架在Kotlin中都是可以使用的。
結(jié)語相比于Scala,Kotlin在實(shí)用性方面下了大功夫,無縫兼容Java,融入Java生態(tài),自身也有簡(jiǎn)潔的語法和強(qiáng)大的DSL能力。(想一想Scala 2.10 2.11 2.12的互不兼容,以及build一個(gè)項(xiàng)目會(huì)下載標(biāo)準(zhǔn)庫的n個(gè)版本,例如2.11.0、2.11.1、2.11.2,也不知道實(shí)際運(yùn)行的是哪個(gè)。)
這些新興的Kotlin框架延續(xù)了Kotlin的簡(jiǎn)潔和強(qiáng)大,相信它們很快就會(huì)展現(xiàn)出光明的前途!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/66645.html
摘要:前戲今年,對(duì)于我個(gè)人而言遭遇了三個(gè)重大的轉(zhuǎn)折點(diǎn)。盡可能的把溝通成本用約定和文檔降低。學(xué)習(xí)的這一年可以說年的學(xué)習(xí),在上半年的精力,放在了技術(shù)上。而下半年則相反。 前戲 今年,對(duì)于我個(gè)人而言遭遇了三個(gè)重大的轉(zhuǎn)折點(diǎn)。 15年9月大三休學(xué)創(chuàng)業(yè),16年9月重新復(fù)學(xué)大三 在2016年4月順利引進(jìn)天使輪,公司從廈門集美區(qū)搬到了深圳南山區(qū) 16年底,我們正在準(zhǔn)備接入A輪 16年與15年相比,總體來...
摘要:是一門最近比較流行的靜態(tài)類型編程語言,而且和一樣同屬系。這個(gè)生成的構(gòu)造函數(shù)是合成的,因此不能從或中直接調(diào)用,但可以使用反射調(diào)用。 showImg(https://segmentfault.com/img/remote/1460000012958496); Kotlin是一門最近比較流行的靜態(tài)類型編程語言,而且和Groovy、Scala一樣同屬Java系。Kotlin具有的很多靜態(tài)語言...
摘要:年已經(jīng)過去,這一年前端領(lǐng)域發(fā)生了什么有哪些技術(shù)和項(xiàng)目引人注目工程師們觀點(diǎn)和看法又有怎樣的變化在此,整理了一些對(duì)過去的年盤點(diǎn)的資料,一是希望能借此提高自己的姿勢(shì)水平,二是希望能為年的學(xué)習(xí)有所指導(dǎo)。 2016年已經(jīng)過去,這一年前端領(lǐng)域發(fā)生了什么?有哪些技術(shù)和項(xiàng)目引人注目?工程師們觀點(diǎn)和看法又有怎樣的變化?在此,整理了一些對(duì)過去的2016年盤點(diǎn)的資料,一是希望能借此提高自己的姿勢(shì)水平,二是希...
摘要:是什么著名廠商開發(fā)的基于的靜態(tài)類型編程語言,聲稱。語法近似和,且已活躍在開發(fā)領(lǐng)域,被譽(yù)為平臺(tái)的。各有千秋,我更認(rèn)同改寫字節(jié)碼。的作用是防止敏感字段被泄露到中,的作用是軟刪除數(shù)據(jù)不可見,但沒有真的刪除。 Kotlin是什么? 著名IDE廠商JetBrains開發(fā)的基于JVM的靜態(tài)類型編程語言,聲稱100%?interoperable?with?Java。Kotlin是由工程師設(shè)計(jì)的,各種...
閱讀 1309·2021-09-27 13:56
閱讀 2340·2019-08-26 10:35
閱讀 3497·2019-08-23 15:53
閱讀 1849·2019-08-23 14:42
閱讀 1233·2019-08-23 14:33
閱讀 3562·2019-08-23 12:36
閱讀 1948·2019-08-22 18:46
閱讀 997·2019-08-22 14:06