Kotlin 是一門好語言,值得你們瞭解一下。html
Vertx 是一個好框架,也值得你們瞭解一下。java
寫過js,也寫過一點點go,主力一直是java。用了kotlin,貌似找到了經常使用語言的平衡點了。node
Kotlin 擁有一些偏函數式的語法(java8 也引入了一些),提供了至關多便捷的api與一些高階函數。從兩天的試用,以及今天搞得這個 Vertx web 項目,從中體會到最爽的有兩點:git
一直很期待能夠指定receiver這個功能。有了這個特性,那麼寫的函數,能夠直接被調用者使用。github
vertx 風格和node的express框架思想一致的,換了一種java的實現。不得不說,node的express 啓發了不少其餘語言的web框架設計。java的vertx,以及go裏面的不少web框架(martin...),不少都有express的影子(難道是我先入爲主?)web
相比傳統的基於Servlet的java web框架,vertx這種基於封裝底層通訊的框架,在速度上和內存佔用上比較有優點。曾經爲了在768M內存的docker容器上跑web應用,先是用相對較輕量級的spring-boot,勉強能夠跑。而後又用了Node 的 express,這個毫無壓力。spring
終於有一個java版本的這種web框架,整個項目打完包,包括依賴的 lib,整個才4-5M的大小(主要是lib大小),過輕量了。docker
下面就看看 Kotlin + Vertx 寫的web項目,展現下kotlin的魅力。你要是比較懶的話,想直接check out代碼,github庫在這裏。express
按照kotlin和vertx官方的配置。
```xml
<groupId>vertx</groupId> <artifactId>com.vertx</artifactId> <version>1.0-SNAPSHOT</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.3</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <manifestEntries> <Main-Class>com.tt.vertx.HelloWorlds</Main-Class> <Main-Verticle>com.tt.vertx.HelloWorlds</Main-Verticle> </manifestEntries> </transformer> </transformers> <artifactSet/> <outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jar</outputFile> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-maven-plugin</artifactId> <version>${kotlin.version}</version> <executions> <execution> <id>compile</id> <phase>process-sources</phase> <goals> <goal>compile</goal> </goals> <configuration> <sourceDirs> <source>src/main/java</source> </sourceDirs> </configuration> </execution> <execution> <id>test-compile</id> <phase>process-test-sources</phase> <goals> <goal>test-compile</goal> </goals> <configuration> <sourceDirs></sourceDirs> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>io.vertx</groupId> <artifactId>vertx-web</artifactId> <version>3.2.1</version> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-stdlib</artifactId> <version>${kotlin.version}</version> </dependency> </dependencies> <properties> <kotlin.version>1.0.3</kotlin.version> </properties>
```
和spring-boot 同樣,vertx 的程序入口也是一個靜態的main函數。
class HelloWorlds : AbstractVerticle() { companion object{ @JvmStatic fun main(args: Array<String>){ var vertx = Vertx.vertx() vertx.deployVerticle(HelloWorlds()) } } override fun start() { var router = customRouter(vertx) println("server running on 8888") vertx.createHttpServer().requestHandler({ handler -> router.accept(handler)}).listen(8888) } }
若是寫過nodejs應用,這段代碼看起來就很簡單了。繼承vertx的啓動類,在啓動的時候,設置路由,綁定http server的端口。
注意
和普通的kotlin運行類不同,入口主類須要打jar包的時候,主方法(main)必定是要是java的標準靜態方法. 須要加 @JvmStatic 標註一下。不然運行打出來的jar包,會找不到靜態主入口。
在這裏,封裝了一下路由,提取到了單獨的文件中。
fun customRouter(vertx : Vertx) : Router { var router = Router.router(vertx) router.route("/").handler({c -> c.response().html().end("hello world")}) router.route("/json").handler({c -> c.response().json().end(Json.encode(Entity("name","sss")))}) return router } fun HttpServerResponse.html() : HttpServerResponse { return this.putHeader("content-type","text/html") } fun HttpServerResponse.json() : HttpServerResponse { return this.putHeader("content-type","application/json; charset=utf-8") }
讓我以爲kotlin拯救了個人地方就在這一段路由代碼裏。
先看一下,以前用純java寫的路由版本是什麼樣的吧,對比一下。
java版本:
router.route("/").handler(context -> context.response().putHeader("content-type","text/html").end("hello world")); router.route("/json").handler(context -> { context.response().putHeader("content-type","application/json; charset=utf-8") .end(Json.encodePrettily(new Entity("hello","world"))); });
在java版本里面,給每一個請求加header的時候,是要加 .putHeader("content-type","xxxx")
的。
試想一下,若是咱們有上百個路由的話,每一個頭裏面都要指定這些header,多痛苦。根據經驗,咱們可能想把它提出來,當作一個方法。因而咱們須要寫一個工具類之類的,給context.response()
的結果 HttpServerResponse 加上header,而後再返回這個 HttpServerResponse,最直觀的大概寫法應該是:
SomeUtil.setHeader(context.response()).end('xxx')
無論怎麼說,由於java的語法限制,咱們貌似只能這麼寫(若是有更好的方法,請你們共享一下)。
看一下kotlin版本的,把加header的操做提了出來,弄成了兩個函數。這兩個函數是函數接收字面量和擴展函數的結合體,使用擴展函數,這是個,也必須聲明一個函數的接受者類型。
咱們定義html() 和 json() 函數, 這兩個方法只能用HttpServerResponse 去執行它,而且返回執行後的該 HttpServerResponse。 在擴展函數裏面,this指向的是該函數的調用者。語法官方有詳細文檔,就少說了(好多語法我也沒有看完 ORZ )。
這個特性超級好用,尤爲是在這種鏈式的調用裏面,咱們不用在去另寫寫轉換方法,不用在把要轉換的對象當參數來回傳遞了。
data class Entity(var name:String,var description:String){}
第一次寫這個bean的時候,我寫錯了,不管如何,在路由裏面,就是沒法取到該bean構造後的值。看了官方文檔才知道,這個類是須要加一個data前綴的,這樣纔會生成 equals ,hashCode ,Setter, Getter 等這些方法。
主要代碼都在這裏了,完整的代碼在這裏。
用kotlin , 感受很幸福,相見恨晚。
代碼寫的少,對java 是一種強力的補充。它和java之間,徹底能夠相互調用,是一門很不錯的語言,之後能夠慢慢用起來了,還有不少東西值得去探索。
還有一點仍是提一提吧,kotlin親爹jetbrains, Idea 親爹也是 jetbrains。Idea對自家的這門語言支持的至關的不錯,你們均可以試試。另: 放棄Eclipse吧,別再折磨本身啦。
很久沒寫這麼長的文章了,如今國內kotlin相關的東西也很少,但願這篇能有點做用。國內好多文字都隨意轉載,常常見到不署名原做做者地址的。知識靠傳播才能影響更多人,也但願你們轉載的話標註一下文章的原地址。