Kotlinã¯Androidéçºè
ã®éã§äººæ°ã®ããããŒã«ã§ããããåç¥ã®ããã«ããããå¯äžã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãããŸããã ãã®ãããåçŽãªWebãµãŒãã¹ãäœæããããšã«ãããšããKotlinã ãã§äœæããã®ã劥åœãšæãããŸããã
Spring Frameworkãå¯äžã®ãªãã·ã§ã³ã§ã¯ãªãããšãããããŸããã å¥ã®åŒ·åãªéåæã®ä»£æ¿ææ®µ-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ãªãã·ã§ã³ã«èå³ããããŸããã
- ããã©ãŒãã³ã¹ãšéåææ§ãããŒã¹ãšãªã£ãŠããNettyã«å°ãªãããæè¬
- éçºã¢ãããŒããç°¡çŽ åããã·ã³ã°ã«ã¹ã¬ããã¢ãã«
- ã¢ããªã±ãŒã·ã§ã³ããåçŽããšåŒã°ããæå°éã®ã»ã«ã«åå²ãã
- 忣ã€ãã³ããã¹ã«ãããèšè¿°ãããŠããèšèªã«é¢ä¿ãªããåã
ã®é ç¹ãçžäºã«éä¿¡ã§ããŸãã
ãã®ãµã€ãã«ã¯ãã§ã«ããã«é¢ããè¯ãèšäºããã£ãã®ã§ãããã§ãã¬ãŒã ã¯ãŒã¯èªäœã®èª¬æã¯å®äºã§ãã ç§ã®ä»äºã¯ãKotlinã§ããããã¹ãŠã®ã¢ã¡ããã£ãã©ã®ããã«äœ¿çšã§ãããã瀺ãããšã§ãã
ææŠãã
å³¶ïŒããšãã°ã Kotlin ïŒããã³ãããã®å³¶ãäœçœ®ããåœã®ãªã¹ããRESTã¢ãã«ã«åŸã£ãŠJSON圢åŒã§è¿ãWebãµãŒãã¹ãå¿
èŠã ãšããŸãã
GET /islands
- ãã¹ãŠã®å³¶ãšåœã®ãªã¹ã
GET /countries
- å³¶ããããã¹ãŠã®åœã®ãªã¹ã
GET /countries/:code
- ISO 3166ã³ãŒãã«ããåœ
ããã¯ç¹ã«äŸ¿å©ãª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 } }
ã¡ãœããã®ç°¡åãªæŠèŠïŒ
fetchIslands()
ã¯ãåœãšå³¶ã®ãªã¹ãå
šäœãè¿ããŸãfetchCountries(code)
map
-å³¶ã®ãªã¹ãããåœãååŸããŸãdistinct
ã¹ã€ãŒãã®ç¹°ãè¿ãïŒãªãŒã¹ãã©ãªã¢ïŒfilter
æå®ãããã³ãŒãïŒååšããå ŽåïŒã§ãã£ã«ã¿ãªã³ã°ããŸãsortedBy
ã³ãŒãã§ãœãŒã
ãã®æå°éã®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()) } } }
äžèšã®ã³ãŒãã¯æ¬¡ã®ããšãè¡ããŸãã
- æ°ããHTTPãµãŒããŒãäœæããŸã
- ãªã¯ãšã¹ããã«ãŒã¿ãŒã«è»¢éããŸã
- ãã©ã¡ãŒã¿ãŒã§æå®ãããããŒãïŒãŸãã¯ããã©ã«ãã§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ã€ã ãã§ãã
- vertx-core-Vert.xã®ã¡ã€ã³ã³ã¢
- vertx-web-Webãæäœããããã®Vert.xã®ã¢ããªã³
- kotlin-stdlib-jre8-Kotlinæšæºã©ã€ãã©ãªïŒJRE 8çšïŒ
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ã«ããããã€ãããŸãã
ãæž
èŽããããšãããããŸããïŒ
åç
§è³æ