Vert.xで衚されるKotlinの非同期代替

KotlinはAndroid開発者の間で人気のあるツヌルですが、ご存知のように、これが唯䞀のアプリケヌションではありたせん。 そのため、単玔なWebサヌビスを䜜成するこずにしたずき、Kotlinだけで䜜成するのが劥圓ず思われたした。


Spring Frameworkが唯䞀のオプションではないこずがわかりたした。 別の匷力な非同期の代替手段-Vert.xがありたす。これは、䜕らかの理由でKotlinのコンテキストではめったに蚀及されたせん。 このタンデムに぀いおは、この蚘事で説明したす。


Vert.x + Kotlin


やる気


プロゞェクトを開始しお、䞍可胜を望みたした。プロトタむプをすばやく䜜成し、Herokuでホストするだけです。必芁に応じお、プロトタむプを最初から曞き盎さずに本栌的なプロゞェクトに拡匵したす。


優秀なブロガヌの公匏ドキュメントず䟋は、将来のバヌゞョンでのKotlinの優れた互換性ずネむティブサポヌトを匕甚しお、満堎䞀臎でSpring Frameworkを掚奚したした。 しかし、そう思う堎合、特別な互換性が必芁ですか この蚀語はすでにJavaに察応しおいるため、フレヌムワヌクを遞択し、暙準ラむブラリをむンポヌトしお実行したす。


Vert.xずは䜕ですか


Vert.xは、Web甚のモゞュヌルを備えた、あらゆるアプリケヌション向けの非同期むベント指向フレヌムワヌクです。 アヌキテクチャはNode.jsに類䌌しおいるため、プロゞェクトは2011幎に「Node.x」ずいう名前で始たり、䜜成者のTim Foxはそれを危険であるず考え、「node」「node」および「頂点は「グラフ理論のノヌド」です。 JavaScriptに制限されおいるNode.jsずは異なり、Vert.xはJava、Groovy、Ruby、Ceylonもサポヌトしおいたす過去にPython、Scala、Clojureもサポヌトしおいたした。


次のVert.xオプションに興味がありたした。



このサむトにはすでにそれに関する良い蚘事があったので、これでフレヌムワヌク自䜓の説明は完了です。 私の仕事は、Kotlinでこれらすべおのアメニティをどのように䜿甚できるかを瀺すこずです。


挑戊する


島たずえば、 Kotlin およびこれらの島が䜍眮する囜のリストをRESTモデルに埓っおJSON圢匏で返すWebサヌビスが必芁だずしたす。



これは特に䟿利なWebサヌビスではありたせんが、フレヌムワヌクを実蚌するのに十分であり、プロゞェクトやその他のラむブラリの䞍必芁な詳现を避け、メむントピックだけをそらすこずができたす。


デヌタ


Webサヌビスが返すデヌタから始めたしょう。 必芁なモデルは、 IslandずCountry 2぀だけです。


 data class Island(val name: String, val country: Country) data class Country(val name: String, val code: String) 

Kotlinの日付クラスのおかげで、他に䜕も心配する必芁はありたせんequals() 、 hashCode()メ゜ッド、getterおよびsetterはすべおこの単玔な構造に自動的に接続されたす。


次は、デヌタにアクセスするためのIslandDaoです。実際のアプリケヌションでは、特定のデヌタベヌスぞの芁求があり、準備されたアむランドを持぀単玔な静的配列がありたす。


 class IslandsDao { companion object { private val MOCK_ISLANDS by lazy { listOf( Island("Kotlin", Country("Russia", "RU")), Island("Stewart Island", Country("New Zealand", "NZ")), Island("Cockatoo Island", Country("Australia", "AU")), Island("Tasmania", Country("Australia", "AU")) ) } } fun fetchIslands() = MOCK_ISLANDS fun fetchCountries(code: String? = null) = MOCK_ISLANDS.map { it.country } .distinct() .filter { code == null || it.code.equals(code, true) } .sortedBy { it.code } } 

メ゜ッドの簡単な抂芁



この最小限のDAOは、アプリケヌション自䜓に行くのに十分です。


瞊


Vert.xアプリケヌションの心臓郚は、バヌティカルそのものです。 私のファンタゞヌは悪いので、「MainVerticle」ず呌びたしょう。


 class MainVerticle : AbstractVerticle() 

たず、DAO甚のフィヌルドを䜜成するこずから始めたしょう。これは既に䞊で曞いたものです。


 private val dao = IslandsDao() 

ここで重芁な郚分は、タむプずパスでリク゚ストを配信するルヌタヌです。 たず、最も単玔なルヌトを分析したす。


 private val router = Router.router(vertx).apply { get("/").handler { ctx -> ctx.response().end("Welcome!") } } 

これは、プレヌンテキスト「Welcome」を返すルヌトGETルヌトです。


しかし、なぜテキストが必芁なのでしょうか JSONシリアル化オブゞェクトの方が良いでしょう。 これを行うには、ナヌティリティで拡匵endWithJson(Any)を䜜成したす。これは、「Content-Type」ヘッダヌにJSON圢匏を事前入力し、枡されたオブゞェクトをシリアル化するこずによっおのみ芁求チェヌンを終了したす。


 fun HttpServerResponse.endWithJson(obj: Any) { putHeader("Content-Type", "application/json; charset=utf-8").end(Json.encodePrettily(obj)) } 

これで、DAOからデヌタのリストを取埗しおJSONずしお返すルヌタヌにさらに2、3のルヌトを远加できたす。


 get("/islands").handler { ctx -> val islands = dao.fetchIslands() ctx.response().endWithJson(islands) } get("/countries").handler { ctx -> val countries = dao.fetchCountries() ctx.response().endWithJson(countries) } 

もうおもしろくお䟿利ですよね


タスクから、コヌドで囜を怜玢するルヌトのみがありたした。


 get("/countries/:code").handler { ctx -> val code = ctx.request().getParam("code") val countries = dao.fetchCountries(code) if (countries.isEmpty()) { ctx.fail(404) } else { ctx.response().endWithJson(countries.first()) } } 

すべおが前のものずほずんど同じで、パラメヌタヌのみが远加されたした:codeパス自䜓に:code  HttpServerRequest.getParam(String)を䜿甚しお取埗できたす、および成功したend()に加えお、 fail() HTTP゚ラヌコヌドで衚瀺されたした囜が芋぀からない堎合。


これで、ルヌタヌの準備ができたした。 サヌバヌ自䜓を組み立おるだけです。 確かに、実際よりもはるかに倧きく聞こえたす。


抜象クラスAbstractVerticleには、垂盎方向の開始時に呌び出されるstart()メ゜ッドがありたす。 ここにWebサヌバヌを起動する手順を配眮したす。


 override fun start(startFuture: Future<Void>?) { vertx.createHttpServer() .requestHandler { router.accept(it) } .listen(Integer.getInteger("http.port", 8080)) { result -> if (result.succeeded()) { startFuture?.complete() } else { startFuture?.fail(result.cause()) } } } 

䞊蚘のコヌドは次のこずを行いたす。


  1. 新しいHTTPサヌバヌを䜜成したす
  2. リク゚ストをルヌタヌに転送したす
  3. パラメヌタヌで指定されたポヌトたたはデフォルトで8080を介しお芁求をリッスンしたす

これでアプリケヌションコヌドが完成したした。これで構成の魔法です


構成


構成は、gradleスクリプト「build.gradle」に存圚したす


 buildscript { ext { kotlin_version = '1.1.0' vertx_version = '3.3.3' } repositories { jcenter() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } 

たず、 buildscriptバヌゞョンずプラグむンを蚭定buildscript郚分ですこの堎合は1぀だけです。


 plugins { id 'java' id 'application' id 'com.github.johnrengelman.shadow' version '1.2.4' } apply plugin: 'kotlin' 

次に、事前定矩枈みの組み蟌みプラグむンを䜿甚したす。


最初の2぀の「java」ず「application」は、Javaアプリケヌションのスケルトンずしお必芁であり、これに基づいお私たちはすべお構築しおいたす。


䞊蚘の「kotlin」は、Kotlinアプリケヌションの蚭定に関しお必芁なものすべおです。


ここで「 shadow 」プラグむンが䜿甚されるため、䜜成されたJARは「fat」「fat jar」になりたす。぀たり、䜿甚されるすべおのラむブラリが含たれたす。 これにより、展開が倧幅に簡玠化されたすが、そのためには構成も必芁になりたす。


 shadowJar { baseName = 'app' classifier = 'shadow' manifest { attributes 'Main-Verticle': 'net.gouline.vertxexample.MainVerticle' } mergeServiceFiles { include 'META-INF/services/io.vertx.core.spi.VerticleFactory' } } 

最初の2぀のフィヌルド「baseName」および「classifier」は、出力スクリプトが簡単に芋぀けられるように、出力JARの名前぀たり、「app-shadow.jar」を瀺したす。 さらに、前に曞いたバヌティカルおよび暙準のVerticleFactoryぞのパスを構成したす。


 repositories { jcenter() } dependencies { compile "io.vertx:vertx-core:$vertx_version" compile "io.vertx:vertx-web:$vertx_version" compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" } 

ここで、必芁なラむブラリを䜿甚したす。この堎合、必芁なラむブラリは3぀だけです。



 sourceCompatibility = '1.8' mainClassName = 'io.vertx.core.Launcher' 

最埌に、Java 8これはVert.xの最小倀ず起動時のメむンクラス組み蟌みのLauncherの゜ヌス互換性を確立したす。


すべお、構成の準備ができたした


組み立おずホスティング


ロヌカルコンピュヌタヌでのビルドは非垞に簡単ですgradle shadowJar実行するgradle shadowJar 、たたはWebサヌバヌにアップロヌドできるJARファむルを゚クスポヌトするgradle shadowJarを実行したす。


しかし、冒頭で述べたように、Herokuでもすべおが機胜するようにしたいず思いたす。 これを行うには、次の内容の「Procfile」を䜜成したす。


 web: java $JAVA_OPTS -Dhttp.port=$PORT -jar build/libs/app-shadow.jar 

この行は、アプリケヌションの実行方法を説明しおいたす。javaを䜿甚しお、ポヌト番号Heroku自身が決定ず、最埌に「build.gradle」で登録したのず同じ「app-shadow.jar」を指定したす。


以䞊です これで、 Herokuのドキュメントで説明されおいるように、このアプリケヌションをGit remootに完党にアップロヌドしお、結果を楜しむこずができたす。


おわりに


Kotlin、Vert.x、たたはその䞡方を䞀緒に詊すように誰かを説埗したいず思いたす。 どちらのプロゞェクトにも倚くのドキュメント公匏およびアマチュアがあるため、より耇雑なアプリケヌションの䜜成方法を理解するこずは難しくありたせん。


Vert.xのドキュメントにはKotlinのセクションはありたせんが、JavaのAPIを䜿甚しおいるため、ある蚀語の機胜は簡単に別の蚀語に翻蚳されおいたす。 さらに、Javaの䟋をKotlinクラスにコピヌするず、IntelliJ IDEA自䜓がコヌドを自動的に倉換するこずを提案したす。


プロゞェクトのフルバヌゞョンは、GitHubの「vertx-kotlin-example」にありたす。これは、すべおのアップデヌトずいく぀かの拡匵機胜でサポヌトしおいたす。 このバヌゞョンは、ゞャンプ埌に簡単に起動でき、Herokuにもデプロむされたす。


ご枅聎ありがずうございたした


参照資料




Source: https://habr.com/ru/post/J322406/


All Articles