1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        簡單、有趣的Kotlin異步微服務框架(一)

        共 25049字,需瀏覽 51分鐘

         ·

        2021-04-27 23:15

        1. 寫在前面

        「Flutter異步編程相關的系列文章」已經(jīng)講解完畢后,大概已經(jīng)兩周沒有發(fā)布文章,因為我又開始在籌劃了另一個Kotlin相關的專題: 「Kotlin微服務框架Ktor」。這次專題主要是介紹Kotlin在服務端應用的一個微服務異步web框架。

        「為什么又開始Kotlin服務端Ktor專題呢?」

        ?

        因為之前在2020年度總結文章也說過,后續(xù)會主要focus在Kotlin、Flutter、面試三大主題展開一系列文章總結,所以開始「Kotlin服務端Ktor專題」也是在規(guī)劃路線之中。不僅會涉及到Kotlin服務端專題后續(xù)還會在Kotlin jetpack Compose方面、Flutter系列都會展開。

        ?

        「原來Flutter專題會繼續(xù)嗎?此次Kotlin服務端Ktor專題文章,F(xiàn)lutter學習者有必要看嗎?」

        ?

        「Flutter專題當然會繼續(xù)」,此次開始「Kotlin服務端Ktor專題」是希望最后會通過「Ktor作為API服務后端框架+Flutter作為頁面前臺」搭建一套完整的從前到后的全棧應用。我們都知道作為一名客戶端或前端開發(fā)者,上手后端門檻是比較高的。比如Java語言的Spring、SpringBoot框架,Go、python相關的后端框架等等。而現(xiàn)在的「Ktor」就是一套非常非常簡單、輕量級的異步Kotlin后端框架, 它比SpringBoot更加輕量級,僅僅只需少量代碼就能快速搭建一套API后端服務。

        ?

        個人還是強烈推薦Flutter學習者學習下 , 「特別是有了Kotlin基礎的Android開發(fā)者」 。對于我們大前端開發(fā)者很多的能力思維還僅僅停留在大前端,但是如果你能有一項后端開發(fā)的技能,那么你思考問題和解決問題角度就會不一樣的。當然我們不需要像后端開發(fā)者那樣很精通后端開發(fā)領域,但是如果能掌握后端基本的開發(fā)和使用,還是有很大的幫助的。至少之前作為一名Flutter開發(fā)者,學習完后可以自己從前端UI頁面搭建到后端API設計、數(shù)據(jù)表設計擼一整套的應用。為什么不推薦客戶端開發(fā)者去直接學Spring或SpringBoot,說真的因為框架東西比較多,成本比較高,所以這次Ktor這個微服務框架簡單且易用,學習成本較低,所以還是值得試試的。以下這張圖就是后續(xù)Ktor專題路線的規(guī)劃,下面就直接進入正題~

        2. 什么是Ktor

        2.1 Ktor基本介紹

        用Ktor官方(https://ktor.io/)一句話來介紹: 「Ktor是一個用于創(chuàng)建微服務、web應用程序等異步框架,它很簡單、有趣并且免費開源」。它是由jetbrains官方開源,目前已經(jīng)有8.2K+ star (https://github.com/ktorio/ktor),該框架在國內大家可能比較陌生但是在國外還是很受歡迎的,Ktor可以說是為Kotlin中異步而生的框架,它最底層基于Kotlin Coroutine協(xié)程框架,支持了Client、Server雙端異步特性并且在Client、Server雙端上對WebSocket、Socket有了很好的支持。此外它整體具有以下幾種特性:

        • 「輕量級」

        Ktor框架可以說是非常輕量級,僅僅有一些Ktor基礎引擎內容,并沒有冗雜一些其他的功能,甚至日志功能都沒有,但是你可以任意選擇定制你僅僅需要的功能,以構件形式可插拔地集成到Ktor框架中。

        • 「可擴展性強」

        可擴展性可以說是Ktor框架又一大亮點之一,Ktor框架的本質就Pipeline管道,任何的功能構件都可以可插拔方式集成在Pipeline中。比如Ktor官方提供一系列構件用于構建所需的功能,使用起來非常簡單方便。

        • 「多平臺」

        借助「Kotlin Multiplatform」技術構建,可以在任何地方部署Ktor應用程序.

        • 「異步」

        Ktor底層是基于Kotlin協(xié)程構建的,Ktor的異步具有很高的可伸縮性,并且利用其非阻塞式特性,從此擺脫了異步回調地獄。

        2.2 Ktor的架構組成

        Ktor Framework主要分為以下幾層,最底層核心是Kotlin協(xié)程和基本SDK,然后往上是Ktor核心基礎層,包括了引擎、管道、構件、路由、監(jiān)控等;再往上就是四大主要功能模塊分別是Client模塊、Server模塊、Socket模塊、WebSocket模塊。那么該專題主要是focus在Server模塊,主要利用Server模塊來構件web后端服務。關于WebSocket實際上Ktor分別在Client WebSocket和Server WebSocket兩個層面都給了很大的支持。后續(xù)會基于WebSocket使用構建一個實時IM應用的例子。所以整體上來看Ktor框架還是比較簡單和輕量級的,最為功能豐富在于它的功能構件(Feature), 幾乎后續(xù)所有web后端服務功能都可以看成作為它的一個功能構件(Feature)集成到Ktor中,比如序列化(gson、jackson)、日志、auth認證、template模版(freemarker、velocity)、CORS(解決跨域問題配置)、Session等功能

        3. 如何構建一個簡單的Ktor Server應用

        構建一個Ktor Server應用可以說是非常非常簡單,僅僅只需簡單十幾行代碼就構建一個Server服務。而構建Ktor Server應用主要分為兩種 「: 一種是通過embeddedServer方式構建,另一種則是通過EngineMain方式構建?!?/strong>

        3.1 通過「embeddedServer方式構建」

        通過embeddedServer函數(shù)構建Ktor Server應用是一種最為簡單的方式也是官方默認推薦使用的一種方式。embeddedServer函數(shù)是通過在代碼中配置服務器參數(shù)并快速運行應用程序的簡單方法,不需要額外配置文件。比如在下面的代碼段中,它接收服務器容器引擎類型和端口參作為參數(shù),傳入Netty服務器容器引擎和端口8080,啟動應用后就會在8080端口監(jiān)聽。

        • Application.kt
        package com.mikyou.ktor.samplecom.mikyou.ktor.sample

        import io.ktor.application.*
        import io.ktor.http.*
        import io.ktor.response.*
        import io.ktor.routing.*
        import io.ktor.server.engine.*
        import io.ktor.server.netty.*

        fun main(args: Array<String>) {
            embeddedServer(Netty, port = 8080) {//除了支持Netty還支持Jetty、Tomcat、CIO(Coroutine-based I/O)
                routing {
                    get("/") {
                        call.respondText("Hello Ktor")
                    }
                }
            }.start(wait = true)
        }

        3.2 通過EngineMain方式構建

        EngineMain方式則是選定的引擎啟動服務器,并加載外部一個 application.conf 文件中指定的應用程序模塊. 然后在 application.conf 配置文件中配置應用啟動參數(shù),比如服務監(jiān)聽端口等

        • Application.kt
        package com.mikyou.ktor.sample

        import io.ktor.application.*
        import io.ktor.response.*
        import io.ktor.routing.*

        fun main(args: Array<String>)Unit = io.ktor.server.netty.EngineMain.main(args)

        fun Application.module(testing: Boolean = false) {//該module函數(shù)實際上是Application的擴展函數(shù),要想該函數(shù)運行需要通過application.conf中配置該函數(shù)
            routing {
                get("/") {
                     call.respondText("Hello Ktor")
                }
            }
        }
        • application.conf
        ktor {
            deployment {
                port = 8080 //配置端口
            }
            application {
                modules = [ com.mikyou.ktor.sample.ApplicationKt.module ] //配置加載需要加載的module函數(shù)
            }
        }

        4. 如何架構一個成熟的Ktor應用

        由上面可知構建一個簡單的Ktor Server可以說是非常簡單,然而要構建一個成熟的Ktor Server應用也是類似,主要是多了一些如何模塊化組織業(yè)務模塊和更清晰化去架構業(yè)務。主要分為以下7個步驟:

        4.1 選擇構建Server的方式

        構建Ktor Server應用主要分為兩種: 「一種是通過embeddedServer方式構建,另一種則是通過EngineMain方式構建?!?/strong> 具體的選擇使用方式參考上面第3節(jié)

        4.2 選擇Server Engine

        要想運行Ktor服務器應用程序,就需要首先創(chuàng)建和配置服務器。服務器配置其中就包括服務器引擎配置,各種引擎特定的參數(shù)比如主機地址和啟動端口等等。Ktor支持大多數(shù)目前主流的Server Engine,其中包括:

        • Tomcat
        • Netty
        • Jetty
        • CIO(Coroutine-based I/O)

        此外Ktor框架還提供一種類型引擎TestEngine專門供測試時使用。要想使用上述指定的Server Engine,就需要添加Server Engine相關的依賴,Ktor是既支持Gradle來管理庫的依賴也支持Maven來管理。

        4.3 配置服務參數(shù)

        配置服務引擎參數(shù),由于構建Server方式不同,所以配置引擎參數(shù)也不一樣。對于embeddedServer函數(shù)方式構建的Ktor應用可以直接通過代碼函數(shù)參數(shù)方式指定,對于EngineMain方式則通過修改配置文件 application.conf 。

        4.3.1 embeddedServer函數(shù)方式
        fun main(args: Array<String>) {
            embeddedServer(Tomcat, port = 8080) {//配置了服務器引擎類型和啟動端口
                routing {
                    get("/") {
                        call.respondText("Hello Ktor")
                    }
                }
            }.start(wait = true)
        }

        //除了服務器引擎類型和啟動端口的配置,還支持一些參數(shù)的配置

        fun main() {
            embeddedServer(Netty, port = 8080, configure = {
                connectionGroupSize = 2 //指定用于接收連接的Event Group的大小
                workerGroupSize = 5 //指定用于處理連接,解析消息和執(zhí)行引擎的內部工作的Event Group的大小,
                callGroupSize = 10 //指定用于運行應用程序代碼的Event Group的大小
            }) {
                routing {
                    get("/") {
                        call.respondText("Hello Ktor")
                    }
                }
            }.start(wait = true)
        }
        //設置可以定制一個EngineEnvironment用于替代默認的ApplicationEngineEnvironment,我們可以通過源碼可知,embeddedServer函數(shù)內部默認構建一個ApplicationEngineEnvironment。
        fun main() {
             embeddedServer(Netty, environment = applicationEngineEnvironment {
                log = LoggerFactory.getLogger("ktor.application")
                config = HoconApplicationConfig(ConfigFactory.load())
                
                module {
                    main()
                }
                
                connector {
                    port = 8080
                    host = "127.0.0.1"
                }
            }).start(true)
        }
        4.3.2 EngineMain方式
        • 如果是選擇EngineMain方式構建Server, 那么就需要通過修改 applicaton.conf
        ktor {
            application {
                modules = [ com.mikyou.ktor.sample.ApplicationKt.module ] //配置加載需要加載的module模塊,這里配置實際上就是Application中module擴展函數(shù)
            }
        }

        //除了可以配置需要加載module模塊,還可以配置端口或主機,SSL等
        ktor {
            deployment {
                port = 8080 //配置端口
                sslPort = 8443 //配置SSL端口
                watch = [ http2 ]
            }
            application {
                modules = [ com.mikyou.ktor.sample.ApplicationKt.module ] //配置加載需要加載的module模塊
            }
            security {//配置SSL簽名和密鑰
                ssl {
                    keyStore = build/test.jks
                    keyAlias = testkey
                    keyStorePassword = test
                    privateKeyPassword = test
                }
            }
        }
        //application.conf文件包含一個自定義jwt(Json Web Token)組,用于存儲JWT設置。
        ktor {
            deployment {
                port = 8080 //配置端口
                sslPort = 8443 //配置SSL端口
                watch = [ http2 ]
            }
            application {
                modules = [ com.mikyou.ktor.sample.ApplicationKt.module ] //配置加載需要加載的module模塊
            }
            security {//配置SSL簽名和密鑰
                ssl {
                    keyStore = build/test.jks
                    keyAlias = testkey
                    keyStorePassword = test
                    privateKeyPassword = test
                }
            }
            jwt {//JWT配置
               domain = "https://jwt-provider-domain/"
               audience = "jwt-audience"
               realm = "ktor sample app"
            }
        }
        • 預定義屬性
        • 命令行運行

        可以使用command運行ktor的jar,并且指定端口

        java -jar sample-app.jar -port=8080

        可以通過config參數(shù)指定xxx.conf的路徑

        java -jar sample-app.jar -config=xxx.conf

        還可以通過-P指定運行應用程序代碼的Event Group的大小

        java -jar sample-app.jar -P:ktor.deployment.callGroupSize=7
        • 代碼中讀取application.conf中的配置

        代碼中讀取application.conf中配置是一件很實用的操作,比如連接數(shù)據(jù)庫時配置都可以通過自定義屬性來實現(xiàn)。比如下面這個例子:

        ktor {
            deployment {//預定義屬性
                port = 8889
                host = www.youkmi.cn
            }

            application {
                modules = [ com.mikyou.ApplicationKt.module ]
            }
            
            #LOCAL(本地環(huán)境)、PRE(預發(fā)環(huán)境)、ONLINE(線上環(huán)境)
            env = LOCAL//自定義屬性
            security {//把db相關配置放入security,日志輸出會對該部分內容用*進行隱藏處理
              localDb {//自定義屬性localDb
                 url = "jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"
                 driver = "com.mysql.cj.jdbc.Driver"
                 user = "xxx"
                 password = "xxx"
              }
              remoteDb {//自定義屬性remoteDb
                 url = "jdbc:mysql://192.168.0.101:3306/mydb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"
                 driver = "com.mysql.cj.jdbc.Driver"
                 user = "xxx"
                 password = "xxx"
              }
            }
        }

        在appliction.conf自定義了屬性配置后,如何在Ktor代碼獲取呢?請看如下代碼:

        const val KEY_ENV = "ktor.env"

        //自定義屬性的key,就是根據(jù)配置中層級通過.連接,有點類似JSON的取值調用
        const val KEY_LOCAL_DB_URL = "ktor.security.localDb.url"
        const val KEY_REMOTE_DB_URL = "ktor.security.remoteDb.url"

        const val KEY_LOCAL_DB_DRIVER = "ktor.security.localDb.driver"
        const val KEY_REMOTE_DB_DRIVER = "ktor.security.remoteDb.driver"

        const val KEY_LOCAL_DB_USER = "ktor.security.localDb.user"
        const val KEY_REMOTE_DB_USER = "ktor.security.remoteDb.user"

        const val KEY_LOCAL_DB_PWD = "ktor.security.localDb.password"
        const val KEY_REMOTE_DB_PWD = "ktor.security.remoteDb.password"


        fun Application.configureDb(vararg tables: Table) {
            //獲取當前Env環(huán)境
            //通過Application中environment實例對象拿到其config對象,通過config以key-value形式獲取配置中的值,不過只支持獲取String和List
            val env = environment.config.propertyOrNull(KEY_ENV)?.getString() ?: "LOCAL"
            
            val url = environment
                .config
                .property(if (env == "LOCAL") KEY_LOCAL_DB_URL else KEY_REMOTE_DB_URL)//如果是LOCAL環(huán)境就切換到本地數(shù)據(jù)庫連接方式
                .getString()

            val driver = environment
                .config
                .property(if (env == "LOCAL") KEY_LOCAL_DB_DRIVER else KEY_REMOTE_DB_DRIVER)
                .getString()

            val user = environment
                .config
                .property(if (env == "LOCAL") KEY_LOCAL_DB_USER else KEY_REMOTE_DB_USER)
                .getString()

            val pwd =environment
                .config
                .property(if (env == "LOCAL") KEY_LOCAL_DB_PWD else KEY_REMOTE_DB_PWD)
                .getString()

            //連接數(shù)據(jù)庫
            Database.connect(url = url, driver = driver, user = user, password = pwd)

            //創(chuàng)建數(shù)據(jù)庫表
            transaction {
                tables.forEach {
                    SchemaUtils.create(it)
                }
            }
        }

        4.4 通過Features添加必要功能構件

        在Ktor中一個最典型的請求(Request)-響應(Response)管道模型大致是這樣的: 它從一個請求開始,該請求會被路由到特定的程序處理,并經(jīng)由我們的應用程序邏輯處理,最后做出響應。然而在實際的應用開發(fā)中,并不會這么簡單的,但是本質上Pipeline是不變的。那么在Ktor如何更加將這個簡單管道模型給豐富起來呢?那就是向管道模式添加各種各樣的Feature(功能構件或者功能插件)。

        4.4.1 向管道模型添加功能構件

        在許多應用開發(fā)中經(jīng)常會用到一些基礎通用的功能,比如內容編碼、序列化、cookie、session等,這些基礎通用的功能在Ktor中統(tǒng)稱為**Features(功能構件)。「所有的Features構件都類似一個插件,插入在Request、application Logic和Response切面之間。由上圖可知,當一個請求Request進來后,首先會通過Routing路由機制路由給一個特定的Handler進行處理;然而在把Request交由Handler處理之前可能會經(jīng)過若干個Feature處理;然后Handler處理完這個Request請求,就會將Response響應返回給客戶端,然而在將響應發(fā)送給客戶端之前,它還是可能會經(jīng)過若干個Feature處理,最終Response響應返回到客戶端。可以看出整條從Request到Response鏈路就類似一個工廠流水線,每個Feature各司其職。

        4.4.2 Routing本質上也是一個Feature

        Feature的靈活性和可插拔性非常強大,它可以出現(xiàn)在Request/Response管道模型中任何一個節(jié)點部分。Routing雖然我們稱為路由,但其本質也是一個Feature

        4.4.3 如何安裝Feature

        一般都是在應用初始化的時候去安裝Feature即可,安裝Feature非常簡單。僅僅幾行 install 即可搞定,如果是非內置的 Feature 還需要自己引入相關lib依賴.  除了使用現(xiàn)有的Feature, 還可以自定義Feature,關于如何自定義Feature屬于Ktor高階命題,后續(xù)再展開。

        import io.ktor.features.*
        fun Application.main() {
            install(Routing)
            install(Gson)
            //...
        }

        //除了在main函數(shù)中安裝,還可以在module入口函數(shù)中安裝
        fun Application.module() {
            install(Routing)
            install(Gson)
            //...
        }

        4.5 通過Routing處理請求

        Routing本質上也是一個Feature,所以Routing也需要進行install,然后就可以定義Route Handler處理請求了。

        4.5.1 安裝Routing路由
        import io.ktor.routing.*

        install(Routing) {
            // ...
        }

        //或者直接調用Application的routing擴展函數(shù)
        import io.ktor.routing.*

        routing {
            // ...
        }

        //因為Application的routing擴展函數(shù)內部做了處理,對于未安裝Routing會自動安裝Routing的容錯,可以稍微瞅下源碼
        @ContextDsl
        public fun Application.routing(configuration: Routing.() -> Unit): Routing =
            featureOrNull(Routing)?.apply(configuration) ?: install(Routing, configuration)
            
        //通過源碼可以發(fā)現(xiàn),如果configuration沒有安裝Routing就會自動安裝Routing,所以大家一般看到的Routing都沒有手動install過程,而是直接類似下面的代碼。
        fun main(args: Array<String>) {
            embeddedServer(Tomcat, port = 8080) {
                routing {//直接調用Application的擴展函數(shù)routing,內部做了對于未安裝Routing會自動安裝Routing的容錯處理
                    get("/") {
                        call.respondText("Hello Ktor")
                    }
                }
            }.start(wait = true)
        }
        4.5.2 定義路由處理的Handler

        可以看下下面最簡單的一個get服務的定義,下面用get源碼來解讀:

        fun main(args: Array<String>) {
            embeddedServer(Tomcat, port = 8080) {
                routing {
                    get("/") {//可以看到這個處理get請求的handler,它實際上是一個Route的擴展函數(shù),一起來看看源碼
                        call.respondText("Hello Ktor")
                    }
                }
            }.start(wait = true)
        }

        //Route.get函數(shù)源碼,其實一個Route對象就是一個對應的Handler,
        @ContextDsl
        public fun Route.get(path: String, body: PipelineInterceptor<Unit, ApplicationCall>): Route {
            return route(path, HttpMethod.Get) { //route函數(shù)本質上是一個Route的擴展函數(shù)
                handle(body) //通過調用Route對象來處理的請求
            }
        }

        //route函數(shù)本質上是一個Route的擴展函數(shù)
        @ContextDsl
        public fun Route.route(path: String, method: HttpMethod, build: Route.() -> Unit): Route {
            val selector = HttpMethodRouteSelector(method)
            return createRouteFromPath(path).createChild(selector).apply(build)//最終調用apply返回Route對象,build是傳入handle(body)執(zhí)行的lambda,
            //也就是創(chuàng)建完child后返回一個Route對象,最終再調用它的handle函數(shù)
        }

        4.6 應用模塊化

        為了使得Ktor應用更具有可維護性、靈活性以及,Ktor提供一種思路就是將應用按照業(yè)務維度進行模塊化設計。注意這里模塊化概念并不是在項目中的一個Module,而這里module本質上是一個 Application 的擴展函數(shù)。并且可以在 application.conf 指定某一個或若干個module進行可插拔式的部署和卸載。然后一個Module又包括了一條或若干條Request/Response的管道模型。應用模塊代碼例子如下:

        //定義一個accountModule,實際上是一個Application的擴展函數(shù)
        fun Application.accountModule() {
            routing {
                loginRoute()
                bindPhoneRoute()
                getSmsCodeRoute()
                registerRoute()
            }
        }

        //在application.conf配置加載對應的accountModule模塊
        ktor {
            #LOCAL、PRE、ONLINE
            env = LOCAL
            deployment {
                port = 8889
                host = www.youkmi.cn
            }

            application {
                //可以在modules動態(tài)配置所需加載Module,第一個com.mikyou.ApplicationKt.module默認是主Module,用于加載一些基礎通用的Features,實現(xiàn)模塊的可插拔式的安裝和卸載
                modules = [ "com.mikyou.ApplicationKt.module","com.mikyou.modules.account.AccountModuleKt.accountModule"]//配置accountModule,注意配置路徑,例如定義Account模塊的類文件是AccountModule.kt, 所以它對應類名稱就是AccountModuleKt,所以accountModule模塊類路徑就是com.mikyou.modules.account.AccountModuleKt.accountModule。
            }
            //...
        }

        4.7 應用結構化

        Ktor在提供靈活性方面提供多種方式來組織和結構化應用。

        4.7.1 以文件來形式組織

        將單個文件中相關的路由分組管理,比如應用處理訂單和用戶,就會單獨建立兩個文件: OrderRoutes.kt和CustomerRoutes.kt文件分別管理相關路由請求。

        • OrderRoutes.kt
        fun Route.orderByIdRoute() {
            get("/order/{id}") {

            }
        }

        fun Route.createOrderRoute() {
            post("/order") {

            }
        }
        • CustomerRoutes.kt
        fun Route.customerById() {
            get("/customer/{id}") {

            }
        }

        fun Route.createCustomer() {
            post("/customer") {

            }
        }
        4.7.2 以路由定義形式組織
        fun Application.accountModule() {
            routing {
                loginRoute()
                bindPhoneRoute()
                registerRoute()
            }
        }

        //登錄
        private fun Route.loginRoute() {
            post("/api/login") {
              //...
            }
        }

        //注冊
        private fun Route.registerRoute() {
            post("/api/register") {
                //...
            }
        }

        //綁定手機號
        private fun Route.bindPhoneRoute() {
            post("/api/bindPhone") {
               //...
            }
        }

        5. 使用IntelliJ IDEA快速構建Ktor Server應用

        IntelliJ IDEA提供一個Ktor應用插件可以快速構建Ktor Server應用,其中可以借助Ktor插件可視化地安裝各種Feature功能構件。下面會一步一步引導快速構建一個Ktor Server應用。

        5.1 安裝Ktor插件

        在IDEA中的plugins模塊中,搜索ktor安裝Ktor插件。安裝完Ktor插件后,restart IDEA。

        5.2 創(chuàng)建Ktor應用工程并安裝Features

        打開IDEA,點擊new Project, 選擇左邊欄中的"Ktor"應用,然后輸入Project name,選擇項目路徑、選擇構建系統(tǒng)(Groovy Gradle、Kotlin Gradle或Maven)以及選擇對應的服務器容器的引擎(Netty、Tomcat、Jetty、CIO).點擊next后,就到需要選擇對應安裝的Feature(功能構件),Ktor插件提供了不同類型的Features, 主要有Security、Routing、HTTP、Monitoring、Templating、Serialization、Sockets、Administration幾大類的Feature, 可以按照自己應用的需求,按需安裝即可。Security類型相關的Features:Routing類型相關的Features: 添加Routing構件用于路由請求的處理HTTP類型相關的Features: 添加CORS解決跨域訪問問題監(jiān)控類型相關的Features: 添加監(jiān)控日志構件CallLogging構件樣式模板類型相關的Features: 添加HTML DSL和CSS DSL構件序列化類型相關的Features: 添加Gson構件Sockets類型相關的FeaturesAdministration類型相關的Features最終,下面是我們安裝的所有Features,點擊Finish即可創(chuàng)建Ktor Server工程

        5.3 Ktor應用工程項目結構

        可以看到所有安裝的Features都在plugins包中生成,并在Application類main啟動執(zhí)行的入口函數(shù)進行初始化和配置,并且應用程序默認端口為:8080。

        • Routing Feature默認生成的代碼:
        image.png
        • Template Feature默認生成代碼:
        image.png
        • 序列化Gson Feature默認生成代碼:
        image.png

        5.4 運行Ktor應用

        Ktor應用運行起來后,可以通過localhost訪問上述默認生成的頁面:

        • Routing Feature默認生成的頁面結果: http://localhost:8080/
        image.png
        • Template Feature默認生成的html-dsl頁面結果: http://localhost:8080/html-dsl
        image.png
        • Template Feature默認生成的html-dsl頁面結果: http://localhost:8080/html-css-dsl
        image.png
        • Gson Feature默認生成的頁面結果: http://localhost:8080/json/gson
        image.png

        5.5 Debug Ktor應用

        6. 熊貓先生的小總結

        到這里,有關Ktor系列專題的入門第一篇文章就結束了。后面會繼續(xù)深入Ktor相關的內容,包括如何在Ktor操作數(shù)據(jù)庫,我們會用到Kotlin中的ORM框架Exposed以及如何處理請求然后包裝輸出restful api給到客戶端使用。后續(xù)安排是每周一篇文章分享,分別是Kotlin和Flutter相關文章交替進行。

        感謝關注,熊喵先生愿和你在技術路上一起成長!


        瀏覽 137
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

          <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            成人精品鲁一鲁一区二区 | 国产精品污www在线观看17c | 何兰操逼视频 | 色偷偷AV老熟女一区二 | 操逼大片儿 | 九九99久久精品在免费线bt | 插一区成人精品 | 91香蕉在线 | 天天色操 | 女人脱裤子让男人捅 |