. Ktor
Ktorは、Kotlinチームによって構築されたWebフレームワークで、非同期、高性能、軽量のWebサーバーを作成し、Kotlinの通常のAPIを使用して、ノンブロッキング、マルチプラットフォームのWebクライアントを構築します。
Ktorのサーバー側はJVMに限定されていますが、Ktorのクライアント側はマルチプラットフォームライブラリです。
Ktor のクライアントを Http フレームワークとして使用することは、Kotlin マルチプラットフォームでクロスプラットフォームプロジェクトを構築する際の良い選択です。
Ktorはサーバーエンジンと柔軟な非同期HTTPクライアントの2つの部分から構成されています。現在のリリースでは、HTTPクライアントに焦点を当てています。クライアントはJVM、JS、Android、iOSをサポートするマルチプラットフォームライブラリで、現在ではクロスプラットフォームのモバイルアプリケーションでよく使用されています。
. Ktor サーバーサイドでの使用
Ktorのサーバーサイド・アプリケーションは様々な方法で実行することができます:
- main() で embeddedServer を呼び出し、Ktor アプリケーションを起動します。
- HOCONのapplication.conf設定ファイルを使用してEngineMain main()を実行します。
- ウェブサーバーとしてのサーブレット
- withTestApplication を使用して、Ktor アプリケーションをテスト内で起動します。
Gradle Ktorの設定
KtorはKotlinのコルーチンに依存しているため、Kotlinのバージョン1.3.xが必要です。
Ktorを使用する必要があるモジュールに、以下の依存関係を追加します:
dependencies {
...
implementation "io.ktor:ktor-server-core:${libs.ktor}"
implementation "io.ktor:ktor-server-netty:${libs.ktor}"
}
この後の例では、freemarkerやgsonなど、Ktorの他のアーティファクトを紹介します。
embeddedServer
例としてNettyをサーバーエンジンとして使用し、embeddedServer経由でKtorアプリケーションを起動します:
fun main() {
embeddedServer(Netty, port?:8080, watchPaths = listOf("MainKt"), module = Application::module).start()
}
ApplicationCall && Routing
Ktor のパイプラインは、ルーティング、圧縮などの特定の機能を提供する、1つ以上のプリインストールされたインターセプターで構成され、最終的にリクエストを処理します。
Ktorのルーティングは、DSLを使ったコンフィギュレーションだけでなく、Restfulなアプローチもサポートしています。
ルーティングはルーティングツリーと呼ばれるネストをサポートし、複雑なルールのマッチングやリクエストの再帰的な処理を可能にします。
CORS
デフォルトでは、Ktorはインターセプターを提供し、クロスドメインリソース共有の適切なサポートを可能にします。
まず、アプリケーションにCORS機能をインストールします。
fun Application.main() {
...
install(CORS)
...
}
Ktor CORS 機能のデフォルト設定では、GET、POST、HEAD の HTTP メソッドと以下のヘッダーのみを扱います:
HttpHeaders.Accept
HttpHeaders.AcceptLanguages
HttpHeaders.ContentLanguage
HttpHeaders.ContentType
次の例は、CORS 機能を構成する方法を示しています。
fun Application.main() {
...
install(CORS)
{
method(HttpMethod.Options)
header(HttpHeaders.XForwardedProto)
anyHost()
host("my-host")
// host("my-host:80")
// host("my-host", subDomains = listOf("www"))
// host("my-host", schemes = listOf("http", "https"))
allowCredentials = true
allowNonSimpleContentTypes = true
maxAge = Duration.ofDays(1)
}
...
}
Packing
Ktor アプリケーションをデプロイする場合、fat jar または war パッケージを使用できます。
例えばfat jarの場合、Ktorアプリケーションはgradleのshadowプラグインを使って簡単にパッケージ化できます。
プロジェクトのルートディレクトリにあるbuild.gradleにシャドウプラグインの依存関係を追加します:
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:5.2.0'
......
}
}
次に、パッケージ化したいモジュールに shadow プラグインを追加し、jar パッケージ名と jar パッケージのエントリ Main 関数を出力します:
plugins {
id 'java'
id 'kotlin'
id 'com.github.johnrengelman.shadow'
}
......
shadowJar {
baseName = 'xxx' // jar
manifest {
attributes["Main-Class"] = "xxx.xxx.xxx.xxx" // jar パッケージの主な機能
}
}
.
この記事では、 RxCache 例に、Ktorを使用してディスク・キャッシュからデータを読み込むローカル・キャッシュ・ブラウザの開発について説明します。
RxCacheはJavaとAndroid用のローカルキャッシュです。現在、インメモリ、オフヒープメモリ、ディスクキャッシュをサポートしています。
開発の背景:Ubuntuにデプロイされているデスクトップ・アプリケーションの中には、データを埋め込む必要があるものがいくつかあり、RxCache自体がディスク上のキャッシュをサポートしています。そのため、RxCacheを使って埋めたデータを保存し、ローカルに埋めたデータを表示するブラウザ・アプリケーションが必要です。
RxCache
RxCache はシングルトンなので、まず config() を呼び出して RxCache を構成する必要があります。
RxCache は、メモリ、永続性、およびさまざまなシリアライズ方法という、2 番目のレベルのキャッシュをサポートしています。これらは設定によって反映させることができます。
val rxCache: RxCache by lazy {
val converter: Converter = when (Config.converter) {
"gson" -> GsonConverter()
"fastjson" -> FastJSONConverter()
"moshi" -> MoshiConverter()
"kryo" -> KryoConverter()
"hessian" -> HessianConverter()
"fst" -> FSTConverter()
"protobuf" -> ProtobufConverter()
else -> GsonConverter()
}
RxCache.config {
RxCache.Builder().persistence {
when (Config.type) {
"disk" -> {
val cacheDirectory = File(Config.path) // rxCache 永続層ストレージ・アドレス
if (!cacheDirectory.exists()) {
cacheDirectory.mkdir()
}
DiskImpl(cacheDirectory, converter)
}
"okio" -> {
val cacheDirectory = File(Config.path) // rxCache 永続層ストレージ・アドレス
if (!cacheDirectory.exists()) {
cacheDirectory.mkdir()
}
OkioImpl(cacheDirectory, converter)
}
"mapdb" -> {
val cacheDirectory = File(Config.path) // rxCache 永続層ストレージ・アドレス
MapDBImpl(cacheDirectory, converter)
}
"diskmap"-> {
val cacheDirectory = File(Config.path) // rxCache 永続層ストレージ・アドレス
DiskMapImpl(cacheDirectory, converter)
}
else -> {
val cacheDirectory = File(Config.path) // rxCache 永続層ストレージ・アドレス
if (!cacheDirectory.exists()) {
cacheDirectory.mkdir()
}
DiskImpl(cacheDirectory, converter)
}
}
}
}
RxCache.getRxCache()
}
module
Ktor モジュールは、Application クラスを受け取る開発者定義関数です。
この例では、DefaultHeaders、CallLogging、FreeMarker、ContentNegotiation、Routingがインストールされています。
fun Application.module() {
install(DefaultHeaders)
install(CallLogging)
install(FreeMarker) {
templateLoader = ClassTemplateLoader(this::class.java.classLoader, "templates")
defaultEncoding = "utf-8"
}
install(ContentNegotiation) {
gson {
setDateFormat(DateFormat.LONG)
setPrettyPrinting()
}
}
install(Routing) {
......
}
}
Routing
ルーティングは外部ページを提供します。
install(Routing) {
static("/") {
defaultResource("index.html", "web")
}
post("/saveConfig") {
val postParameters: Parameters = call.receiveParameters()
Config.path = postParameters["path"] ?: ""
Config.type = postParameters["type"] ?: ""
Config.converter = postParameters["converter"] ?: ""
call.respond(FreeMarkerContent("save.ftl", mapOf("config" to Config)))
}
get("/list") {
val file = File(Config.path)
val array = file.list()
call.respond(array)
}
get("/detail/{key}") {
val key = call.parameters["key"]
val json = rxCache.getStringData(key)
call.respondText(json)
}
get("/info") {
val json = rxCache.info
call.respondText(json)
}
}
index.htmlはRxCacheの設定に使用されます。
<html>
<h2>Hi</h2>
RxCache's path: ${config.path} </br>
RxCache's persistence: ${config.type} </br>
RxCache's serialization: ${config.converter} </br>
</html>
リスト・インターフェースと詳細インターフェースは、ディスクに保存されているデータのキーを表示し、キーに基づいてストレージの詳細を照会するために使用されます。
info インタフェースは、キャッシュ内の情報を表示するために使用されます。
スタートアップ
ブラウザはコマンドラインからの引数を解析する kotlinx-cliで設定します。現在のところ、Ktor アプリケーションを起動するポート番号を示す '-p' のみがサポートされています。
ブラウザはサーバーエンジンとしてNettyを使用します。
fun main(args: Array<String>) {
val parser = ArgParser("rxcache-browser")
val port by parser.option(ArgType.Int, shortName = "p", description = "Port number of the local web service")
parser.parse(args)
embeddedServer(Netty, port?:8080, watchPaths = listOf("MainKt"), module = Application::module).start()
}
.
Ktorは最小限のコードと設定でアプリケーションを構築するので、とても簡単です。
シンプルなWebプロジェクトや、外部とのインターフェースを提供するOpenAPIプロジェクトに最適です。もちろん、マイクロサービスの構築にも使えますし、豊富な あります。
RxCache :サンプルコード :




