Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
SpringBootとKtorを雑に比較してみる
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
chiharu terashima
March 25, 2020
Programming
1k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
SpringBootとKtorを雑に比較してみる
chiharu terashima
March 25, 2020
More Decks by chiharu terashima
See All by chiharu terashima
アイテムレビュー基盤で導入したアーキテクチャとその成果 / Item Review Introduction Architecture Outcome
chichi1091
1
3.7k
Other Decks in Programming
See All in Programming
SONY CISC-NEWS NWS-1750 + NWB-225 フレームバッファの NetBSD/news68k ドライバ実装 / OSC2026Hiroshima
tsutsui
0
160
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
7
5.1k
Are APIs Still Relevant in the AI Era?
soyuka
0
360
MVNOの申込からeSIM開通までをiOSアプリでつなぐ- 本人確認・MNP・通信事業者基盤をまたぐ実装
satotakeshi
0
510
選挙速報を多くのユーザーへ 届ける Live Activities 設計
hamayokokuririn
0
190
半永久的に提供し続けられるプライベートクラウドを目指して ― 利用者の認知負荷を抑えるAPI抽象化とハードウェア世代交代の基盤設計
tomokon
0
280
Java 27新機能 / Java 27 new features
kishida
2
180
JPUG勉強会 OSSデータベースの内部構造を理解しよう(第2回)
oga5
0
280
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
3.1k
標準パッケージに uuid が追加された 背景から見る Go らしい意思決定 / go_127_uuid_decision
convto
5
9.1k
wkhtmltopdfの次どうするか問題2026
willnet
2
1.8k
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
490
Featured
See All Featured
Leo the Paperboy
mayatellez
10
2.3k
Mobile First: as difficult as doing things right
swwweet
225
10k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
710
[RailsConf 2023] Rails as a piece of cake
palkan
59
7k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
1k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
750
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
520
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
1
610
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
550
Transcript
SpringBootͱKtorΛ ࡶʹൺֱͯ͠ΈΔ ͳ͕ͷJava #1 2020.03.25 @chichi1091
SpringBootͱKtorΛ ࡶʹൺֱͯ͠ΈΔ ͳ͕ͷJava #1 2020.03.25 @chichi1091
ࣗݾհ • ࣉౢઍʗͯͬ͠ʔʢ@chichi1091ʣ • גࣜձࣾHolmes • αʔόαΠυΤϯδχΞ • SpringBoot(Java,Kotlin),Groovy https://chichi1091.hatenablog.jp/
https://github.com/chichi1091
© Holmes,inc. All right reserved. ܖϚωδϝϯτγεςϜ ʮϗʔϜζΫϥυʯ ܖʹɺ Ϛωδϝϯτͷ ࢹΛɻ
© Holmes,inc. All right reserved. ։ൃڥ
։ൃʹؔΘΔશ৬छੵۃ࠾༻தͰ͢ʂ – ϓϩμΫτϚωʔδϟ – UI/UXσβΠφʔ – webϑϩϯτΤϯυΤϯδχΞ – αʔόαΠυΤϯδχΞ –
SRE
Ktorͱʁ
Ktorͱʁ • KotlinΛ։ൃ͍ͯ͠ΔJetBrains͕ࣾ։ൃͨܰ͠ྔ WebϑϨʔϜϫʔΫ • featureΛՃ͢Δ͜ͱͰ֦ுػೳͷར༻͕Մೳ • ςϯϓϨʔτΤϯδϯ • ೝূػೳ
• DI
SpringBootͱൺֱ
SpringBootͱൺֱ • ීஈ͍ͬͯΔSpringBootͱൺֱ͢Δ͜ͱͰཧղ ΛਂΊ͔ͨͬͨ • 100%KotlinͷϑϨʔϜϫʔΫʹڵຯ͕͋ͬͨ • ӡ༻ʹ͑ΒΕΔ͔ௐ͔ͨͬͨ
ΈࠐΈAPαʔό
ΈࠐΈAPαʔόʢSpringBootʣ • Buildπʔϧʹspring-boot-starter-xxxΛΈࠐΉ ͜ͱͰΓସ͕͑Մೳ • tomcat • jetty • undertow
ΈࠐΈAPαʔόʢKtorʣ • Buildπʔϧʹktor-server-xxxΛΈࠐΉ͜ͱͰ Γସ͕͑Մೳ • Netty • jetty • tomcat
BootRun
BootRun @SpringBootApplication @Controller class Application { @GetMapping("/") fun index(): String
= "Hello, Kotlin" } fun main(args: Array<String>) { runApplication<BlogApplication>(*args) } class Application fun main(args: Array<String>) { val server = embeddedServer(Netty, 8080) { routing { get("/") { call.respond(HttpStatusCode.OK,"Hello, Kotlin") } } } server.start() } 4QSJOH#PPU ,UPS
ςϯϓϨʔτΤϯδϯ
ςϯϓϨʔτΤϯδϯ • SpringBoot • Thymeleaf • Freemarker • Groovy Template
• Ktor • Thymeleaf • Freemarker • Velocity • Mustache • Kotlin DSLͰHTMLCSSΛॻ͘͜ͱՄೳ
ςϯϓϨʔτΤϯδϯʢKotlin DSLʣ get("/styles.css") { call.respondCss { body { backgroundColor =
Color.red } p { fontSize = 2.em } rule("p.myclass") { color = Color.blue } } } suspend inline fun ApplicationCall.respondCss(builder: CSSBuilder.() -> Unit) { this.respondText(CSSBuilder().apply(builder).toString(), ContentType.Text.CSS) } w ,PUMJOίʔυͰ$44Λੜɾग़ྗ
ςϯϓϨʔτΤϯδϯʢKotlin DSLʣ get("/") { call.respondHtml { head { link(rel =
"stylesheet", href = "/styles.css", type = "text/css") } body{ h1 { id = "title" +"ͳ͕ͷJava" } p("myclass") { +"myclass" } ul { for(n in 1..10) { li { onClick = "alert($n)" +"$n" } } } } } } w ,PUMJOίʔυͰ)5.-Λੜɾग़ྗ
Controller
ControllerʢSpringBootʣ @Controller //@RestController @RequestMapping("/users") class UsersApplication{ @GetMapping("/") fun list(): String
= "users routing ok" @GetMapping("/{id}") fun index(@PathVariable(“id") id: String): String = "user $id routing ok" }
ControllerʢKtorʣ fun main(args: Array<String>) { val server = embeddedServer(Netty, 8080)
{ routing { userController() } } server.start() } fun Route.userController() { route("/users") { get() { call.respondText { "users routing ok" } } get("/{id}") { val id = call.parameters["id"] call.respond(HttpStatusCode.OK, "user $id routing ok") } } } w SPVUFͰΤϯυϙΠϯτΛࢦఆ w ͦͷதʹϧʔςΟϯάઃఆ͠ΞΫγϣ ϯΛࢦఆ͢Δ
ྫ֎ϋϯυϥʔ
ControllerʢSpringBootʣ class ExceptionHandler: ResponseEntityExceptionHandler() { @ExceptionHandler(Exception::class) fun handleException(ex: Exception, headers:
HttpHeaders, request: WebRequest): ResponseEntity<Any> { return super.handleExceptionInternal(ex, "handleException", headers , HttpStatus.INTERNAL_SERVER_ERROR, request) } }
ControllerʢKtorʣ fun main() { val server = embeddedServer(Netty, port =
8082) { install(StatusPages) { exception<XxxException>{ cause -> call.respond(HttpStatusCode.InternalServerError) } exception<AuthorizationException>{ cause -> call.respond(HttpStatusCode.Forbidden) } } routing { userController() } } server.start() } class XxxException: RuntimeException() class AuthorizationException: RuntimeException() w ྫ֎ʹΑͬͯฦ͢εςʔλείʔυΛ ఆٛ
Session
SessionʢSpringBootʣ @Controller //@RestController @RequestMapping("/users") class UsersApplication{ @GetMapping("/") fun list(request: HttpServletRequest):
String { val session = request.session session.setAttribute("key", "name") val name = session.getAttribute("key") return "users routing ok" } } w Լهͷྫ4FTTJPOΛར༻͢Δํ๏ w ଞʹ w !4FTTJPO"UUSJCVUFT w !4DPQF ηογϣϯείʔϓ
SessionʢKtorʣ fun main() { val server = embeddedServer(Netty, port =
8082) { install(Sessions) { cookie<MySession>("MY_SESSION") { cookie.extensions["SameSite"] = "lax" } } routing { get() { val session: MySession = call.sessions.get<MySession>() ?: MySession("1") call.sessions.set("MY_SESSION", session.copy("2")) call.respondText { "users routing ${session.id}" } } } } server.start() } data class MySession ( val id: String ) w ʮ.:@4&44*0/ʯ͕$PPLJF໊
DBଓ
DBଓʢSpringBootʣ @Entity data class Users ( @Id @GeneratedValue(strategy=GenerationType.IDENTITY) val id:
Long, val name: String, val birthday: Date ) @Repository interface UsersRepository: JpaRepository<Users, Long> {} @RestController class UsersController( private val usersRepository: UsersRepository ) { @GetMapping(value = ["/"]) @ResponseStatus(HttpStatus.OK) fun index(): List<Users> = usersRepository.findAll() } • ORϚούʔJPA • τϥϯβΫγϣϯAOPͰ੍ޚ
DBଓʢKtorʣ • ORϚούʔExposed • ͪΖΜKotlin • JetBrains͕ࣾ։ൃ • BootRun࣌ʹH2ଓ fun
main(args: Array<String>) { // DBଓ Database.connect("jdbc:h2:mem:ktor_db;DB_CLOSE_DELAY=-1", "org.h2.Driver") val server = embeddedServer(Netty, 8080) { routing { userController() } } server.start() }
DBଓʢKtorʣ // Dao object Users : LongIdTable() { val name:
Column<String> = varchar("name", 50) val birthday: Column<DateTime> = date("birthday") } // Entity class User(id: EntityID<Long>): LongEntity(id) { companion object : LongEntityClass<User>(Users) var name by Users.name var birthday by Users.birthday } fun Route.userController() { val service by inject<UserService>() route("/users") { post() { SchemaUtils.create(Users) // ϚΠάϨʔγϣϯ val cal = Calendar.getInstance() cal.set(Calendar.YEAR, 2020) cal.set(Calendar.MONTH, 3 -1) cal.set(Calendar.DAY_OF_MONTH, 25) val today = DateTime(Calendar.getInstance().timeInMillis) transaction { User.new { name = "kotlin ktor" birthday = DateTime(today) } } call.respondText { "users insert" } } put() { transaction { Users.update ({ Users.id eq 1 }) { it[Users.name] = "kotlin OExposed" } } call.respondText { "users update" } } delete() { transaction { Users.deleteWhere { Users.id eq 1 } } call.respondText { "users delete" } } get() { var result: List<User> = listOf() transaction { result = User.all().sortedByDescending{ it.birthday } } call.respondText { "users routing ${service.getName()}" } } } } w 42-ൃߦ࣌USBOTBDUJPOඞਢ w ݕࡧଞʹ val user: SizedIterable<User> = User.find { Users.id eq 1 } val user: User? = User.findById(1L)
JSON
JSONʢSpringBootʣ @RestController @RequestMapping("/users") class UsersApplication{ @GetMapping("/") fun list(request: HttpServletRequest): ResponseEntity<Json>
{ val json = Json(1,"Kotlin") return ResponseEntity.of(Optional.of(json)) } } data class Json( private val id: Int, private val name: String )
JSONʢKtorʣ fun main() { val server = embeddedServer(Netty, port =
8082) { install(ContentNegotiation) { jackson { configure(SerializationFeature.INDENT_OUTPUT, true) } } routing { get() { call.respond(Json(1, "Ktor")) } } } server.start() } data class Json( private val id: Int, private val name: String ) w JOTUBMMͰ+BDLTPOͷઃఆ w ฦ٫͞ΕΔ+40/Λܗ
DI
DIʢSpringBootʣ @Service class UserService { fun getName(): String { return
"Kotlin" } } @RestController class UserController( private val userService: UserService ) { @GetMapping("/") fun index(): String { return "Hello, ${userService.getName()}" } }
DIʢKtorʣ • KtorͰDI͢ΔʹʮKodeinʯ͔ʮKoinʯΛ͏ • ࠓճKoin fun main() { val server
= embeddedServer(Netty, port = 8082) { install(Koin) { modules(module) } routing { userController() } } server.start() } val module = module(createdAtStart = true) { singleBy<UserService, UserService>() } class UserService { fun getName(): String{ return "Kotlin" } } fun Route.userController() { val service by inject<UserService>() route("/users") { get() { call.respondText { "users routing ${service.getName()}" } } } } w JOTUBMM ,PJO Ͱ%*ίϯςφొ w γϯάϧτϯͰ6TFS4FSWJDFΛొ w JOKFDUͰऔಘ
·ͱΊ
·ͱΊ • SpringBootͱಉͷfeature͕ἧ͍ͬͯΔΑ͏ʹ ײͨ͡ • υΩϡϝϯτΘ͔Γ͍͢(https://ktor.io/) • Githubͷߋ৽׆ൃ • featureͲΜͲΜ૿͑ͦ͏ʁ
• SpringBootΑΓKotlinͬΆ͍ίʔυ͕ॻ͚Δ • ຊ൪ར༻͑ΒΕͦ͏