Slide 1

Slide 1 text

Play Framework 2.5 Ͱͭ͘Δ Web ΞϓϦέʔγϣϯ Tsuyoshi Yoshizawa @ussy00

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Play + Scala ܦݧྺ ● Java Λத৺ʹडୗҊ݅ ● ओʹ Seasar2 ϑϨʔϜϫʔΫ ● Play 2.0 ͔Βຊ֨తʹ Scala Λ৮Δ ● ͍͍ͩͨ 4 ೥͙Β͍ ● αʔϏεΛͭ͘Δͱ͖ʹબఆ ● ຊӡ༻ظؒ͸ 2 ೥

Slide 4

Slide 4 text

Play + Scala ΛબΜͩཧ༝ ● Java 8 ͸·ͩͳ͘ Scala ʹڵຯ ● ίϨΫγϣϯ API ͕ศརͩͬͨ ● Option ͕ॳΊ͔Β૊Έࠐ·Ε͍ͯͨ ● ؆ܿͳίʔυʹͰ͖Δ ● Java ࢿ࢈ʢϥΠϒϥϦʣ͕ར༻Ͱ͖Δ ● ॻ͍ͯΈָ͔ͯͬͨ͠

Slide 5

Slide 5 text

Play Framework makes it easy to build web applications with Java & Scala. Play is based on a lightweight, stateless, web-friendly architecture.

Slide 6

Slide 6 text

RESTful GET /users/:id controllers.UserController.find(id: Long) class UserController extends Controller { def find(id: Long) = Action { implicit request => User.findById(id).map { user => Ok(Json.obj( “id” -> user.id, “name” -> user.name )) }.getOrElse { NotFound(Json.obj( “message” -> “User not found” )) } } } routes UserController.scala

Slide 7

Slide 7 text

εςʔτϨε ● ηογϣϯ৘ใ͸ ΫϥΠΞϯταΠυ (Cookie) ʹจࣈྻΛอ࣋ ● ΩʔΛݩʹ DB/Ehcache/Redis ͳͲʹ อଘ͢Δ ● HMAC-SHA1 ʹΑΔॺ໊ ● play.crypto.secret ҉߸伴ͷΩʔ (application.conf)

Slide 8

Slide 8 text

ϦόʔεϧʔςΟϯά GET /users/:id controllers.UserController.find(id: Long) POST /users/create controllers.UserController.create class UserController extends Controller { def create = Action { implicit request => // ࡞੒ॲཧ val user = ??? Redirect(routes.UserController.find(user.id)) } } ● ίϯύΠϧνΣοΫʹΑΔ҆৺ײ ● ύϥϝʔλʔɺ URL มߋ΁ͷࣗಈ௥ਵ @user.name view

Slide 9

Slide 9 text

ςϯϓϨʔτΤϯδϯ (twirl) @(customer: Customer, orders: List[Order])

Welcome @customer.name!

    @for(order <- orders) {
  • @order.title
  • }
● ίϯύΠϧνΣοΫʹΑΔ҆৺ײ ● Scala ه๏Ͱهड़ view

Slide 10

Slide 10 text

HTTP ϦΫΤετϋϯυϦϯά case class UserData(name: String, age: Int) val userForm = Form( mapping( "name" -> nonEmptyText, "age" -> number(min = 0, max = 100) )(UserData.apply)(UserData.unapply) ) ● ύϥϝʔλʔͷܕ߹Θͤ΋ίϯύΠϧνΣοΫ ● content-type ʹΑΔϋϯυϦϯάରԠ ● application/x-www-form-urlencoded ● application/json

Slide 11

Slide 11 text

Play ෇ଐϥΠϒϥϦ ● Web ΞϓϦΛ࡞੒͢Δ্Ͱ࠷௿ݶͷ ϥΠϒϥϦ͕෇ଐ͍ͯ͠Δ ● Play JSON ● Play WS ● HTTP client ● OAuth client ● Play Filters (CSRF, CORS …)

Slide 12

Slide 12 text

Dependency Injection ● JSR 330 ඪ४࢓༷ʹ४ڌ ● ίϯετϥΫλΠϯδΣΫγϣϯਪ঑ ● Play 2.4 ͔Βಋೖ import javax.inject.Inject import play.api.libs.ws._ class MyComponent @Inject()(wsClient: WSClient) { def request(url: String) = { wsClient.url(url).get() … } }

Slide 13

Slide 13 text

࣮૷੾Γସ͑ྫ ● trait (interface) ʹΑΔ։ൃ؀ڥ/ຊ൪؀ ڥͷ࣮૷੾Γସ͑΋ίʔυͰදݱ class MyModule(environment: Environment, configuration: Configuration) extends AbstractModule { override def configure() = { configuration.getString("storage.type") match { case Some(t) if t == "local" => bind(classOf[StorageService]).to(classOf[LocalStorageService]) case Some(t) if t == "s3" => bind(classOf[StorageService]).to(classOf[S3StorageService]) case t => sys.error(s"The storage type is not supported: $t") } } }

Slide 14

Slide 14 text

ࠃࡍԽରԠ (i18n) ● ϝοηʔδϦιʔε͸ conf/messages ϑΝΠϧʹ key=value ܗࣜͰهड़ ● ϩέʔϧΛ֦ுࢠʹ෇Ճͯ͠ෳ਺ݴޠ ରԠ ● conf/messages.ja-JP ● conf/messages.fr play.i18n.langs=[“en-US”,"ja-JP", “fr”]

Slide 15

Slide 15 text

ࠃࡍԽରԠྫ import javax.inject.Inject import play.api.i18n.I18nSupport class UserController @Inject()(val messagesApi: MessagesApi) extends Controller with I18nSupport { def hello = Action { implicit request => Ok(Json.obj( “text” -> Messages(“hello”) )) } } hello=Hello Scala! hello=͜Μʹͪ͸ Scala! messages.ja-JP messages

Slide 16

Slide 16 text

ࠃࡍԽରԠϫϯϙΠϯτ ● ݴޠͷద༻͸ΫϥΠΞϯτ৘ใ͔Β 1. Cookie (PLAY_LANG) 2. AcceptLanguage (HTTP Header) ● MessagesApi#setLang Ͱ Cookie ʹ൓ө Lang(Locale.JAPAN) Lang.get(“ja-JP”).getOrElse(Lang.defaultLang)

Slide 17

Slide 17 text

͕͍͍͜͜Α Play Framework

Slide 18

Slide 18 text

Hot reloading ● ίϯςφ࠶ىಈͳ͠ʹίʔυ൓ө ● sbt ʹΑΔࠩ෼ίϯύΠϧ ● Ϋϥεϩʔμʔࠩ͠ସ͑ ● ։ൃϞʔυͰ͸σϑΥϧτͰ༗ޮ ● dev/prod/test Ϟʔυ

Slide 19

Slide 19 text

Evolutions ● SQL ͰϑΝΠϧʹΞοϓάϨʔυ/μ΢ ϯάϨʔυΛهड़ ● Scala ͰϩδοΫ͸هड़Ͱ͖ͳ͍ ● HTTP ϦΫΤετ࣌ʹݕ஌ ● ։ൃऀͷ DB Λࣗಈతʹ౷ҰͰ͖Δ

Slide 20

Slide 20 text

ϚΠάϨʔγϣϯ࣮ߦྫ

Slide 21

Slide 21 text

ϚΠάϨʔγϣϯϒϥϯνઓུ

Slide 22

Slide 22 text

ϚΠάϨʔγϣϯϝϦοτ ● ϑΟʔνϟʔϒϥϯν։ൃͱ૬ੑ͕Α͍ ● ϒϥϯνؒͷҠಈ͕͠΍͍͢ ● try&error ͕͠΍͍͢ ● ϑΝΠϧ໊͸࿈൪Ͱ؅ཧ (n.sql) ● Ϛʔδ͢Δͱ͖ʹίϯϑϦΫτΛى͜ ͤ͞ɺϚΠάϨʔγϣϯॱΛݻఆ

Slide 23

Slide 23 text

ϚΠάϨʔγϣϯຊ൪؀ڥྫ ● ຊ൪؀ڥͰ͸ແޮʹ͍ͯ͠Δ ● खಈͰΦϯϥΠϯεΩʔϚมߋରԠ͢ ΔͨΊ෼ׂ࣮ͯ͠ߦ͢Δέʔε͋Γ ● σʔλ݅਺ɺϩοΫͷҧ͍ʹ஫ҙ play.evolutions.enabled=false

Slide 24

Slide 24 text

ଞͷϚΠάϨʔγϣϯπʔϧ ● Play Evolutions ͕ഽʹ߹Θͳ͍ ● ίϚϯυϥΠϯ͔Βద༻͍ͨ͠ ● Java(Scala) ͰϚΠάϨʔγϣϯ͍ͨ͠ ● Flyway ͕͓͢͢Ί ● https://github.com/flyway/flyway- play

Slide 25

Slide 25 text

Typesafe config db { default { driver = org.postgresql.Driver } } ● Java ϥΠϒϥϦ Scala ϥούʔ ● HOCON ܗࣜ (JSON Superset) ● ઃఆϑΝΠϧΛ include Ͱ͖Δʢ্ॻ͖ʣ ● application.conf -> prod.conf -> beta.conf

Slide 26

Slide 26 text

͕͍͍͜͜Α Play ·ͱΊ ● RESTful ϑϨʔϜϫʔΫ ● εέʔϧΞ΢τ͠΍͍͢ ● ա৒ͳ·Ͱͷܕ҆શ ● Ξϊςʔγϣϯ΋΄΅ͳ͘ॻ͍ͯ͋Δ ͱ͓Γʹಈ҆͘৺ײ ● ࢼ͠ͳ͕Β։ൃΛਐΊ͍͚ͯΔ

Slide 27

Slide 27 text

͕͜͜ϋϚΔΑ Play Framework

Slide 28

Slide 28 text

Scala ඇಉظॲཧ import scala.concurrent.ExecutionContext.Implicits.global Future { // Some blocking or expensive code here } ● Future Λ࢖͏͜ͱͰɺॲཧΛඇಉظԽ ͢Δ͜ͱ͕Ͱ͖Δ ● CPU ίΞ਺෼ಉ࣌ʹॲཧ ● Java8 CompletableFuture తͳ΋ͷ

Slide 29

Slide 29 text

Play Scala ඇಉظॲཧ import play.api.libs.concurrent.Execution.Implicits._ ● Future Λ࢖͏ ● import ઌΛมߋ͢Δ͜ͱ ● Play ͸σϑΥϧτ 24 ݸ·ͰͷϦΫΤε τΛฒྻͰड͚औΔ ● Thread Pool ͕ރׇ͢Δͱ৽نϦΫΤε τ͕଴ͪঢ়ଶʹͳΔ

Slide 30

Slide 30 text

σϑΥϧτεϨουϓʔϧௐ੔ akka { actor { default-dispatcher = { fork-join-executor { parallelism-min = 100 parallelism-max = 100 } } } } ● ϦϦʔεલʹඞͣνϡʔχϯά ● DB ࠷େ઀ଓ਺Λ֬ೝ

Slide 31

Slide 31 text

Netty Play Request Default thread pool Other thread pool Play

Slide 32

Slide 32 text

ผεϨουϓʔϧ࡞੒ contexts { http { fork-join-executor { parallelism-factor = 20.0 parallelism-max = 200 } } } val executionContext = akkaSystem.dispatchers.lookup(“contexts.http”) Future { // Some blocking or expensive code here }(executionContext)

Slide 33

Slide 33 text

● ద੾ʹεϨουϓʔϧΛఆٛ͠ύϑΥʔ Ϛϯενϡʔχϯά ● DB ࠷େ઀ଓ਺΋֬ೝ ● εϨουΛա৴͗ͣ͢͠ SQS ͳͲͷ ϝοηʔδΩϡʔ΋ߟྀ Play εϨουϓʔϧ·ͱΊ https://www.playframework.com/documentation/ 2.5.x/ThreadPools

Slide 34

Slide 34 text

ORM ● Slick ● Lightbender ࣾʹΑΔ ORM ● Slick 3.0 ͔ΒඇಉظΞΫηεΛਪ঑ ● ScalikeJDBC ● ૉ௚ʹ͔͚ͯେ͖ͳϋϚϦͳ͠ ● جຊతʹ SQL Ͱهड़͢Δ։ൃʹ ● νϡʔχϯά͍͔ͨ͠Β

Slide 35

Slide 35 text

ϦόʔεϓϩΩγ໰୊ play { http { forwarded.trustedProxies=[“10.0.0.0/8”, "::1", “127.0.0.1"] } } ● Nginx ͳͲϦόʔεϓϩΩγΛஔ͍ͯ IP ΞυϨεΛऔಘ͍ͨ͠ ● ৴པ͢Δ Private ωοτϫʔΫΛࢦఆ

Slide 36

Slide 36 text

Assets ύϑΥʔϚϯε໰୊ ● ϦΫΤετ͝ͱʹεϨουফඅ ● ϦϦʔεϏϧυ࣌ʹ S3 (cloudfront) ʹ Ξοϓϩʔυ͢ΔεΫϦϓτࣗ࡞ ● CDN Λར༻͠ϦΫΤετΛࡹ͔ͳ͍

Slide 37

Slide 37 text

Play ৘ใपΓ ● Stackoverflow ͕ୈೋͷυΩϡϝϯτ ● ೔ຊޠपΓ ● Blog ౳͸ݹ͘ͳΓ͕ͪ ● ༗ࢤͷํʑʹΑΔຊՈ຋༁ ● https://gitter.im/scalajp/public ● @scalajp_gitter (twitter)

Slide 38

Slide 38 text

͕͜͜ବ໨ͩΑ Play Framework

Slide 39

Slide 39 text

ίϯύΠϧ଎౓໰୊ ● Scala ͓໿ଋ໰୊ ● View/Routing ਺͕ଟ͘ͳΔͱίϯύΠ ϧ͕஗͘ͳͬͯ͘Δ ● αϒϓϩδΣΫτ౳ߟྀ͢Δ ● API αʔόʔͱͯ͠ͷར༻ݕ౼

Slide 40

Slide 40 text

ίϯύΠϧ଎౓ྫ 0 50 100 67s 90s MBA 11-inch Mid 2012 (2.0 GHz intel Core i7) MBP Retina 15-inch Early 2013 (2.7 GHz Intel Core i7) ։ൃ࣌͸ຖճΫϦʔϯίϯ ύΠϧ͢ΔΘ͚Ͱ͸ͳ͘ɺ sbt ͕ࠩ෼ίϯύΠϧͯ͘͠ ΕΔ

Slide 41

Slide 41 text

ίϯύΠϧ଎౓վળ sources in (Compile, doc) := Nil, publishArtifact in (Compile, packageDoc) := false build.sbt ● υΩϡϝϯτϑΝΠϧੜ੒͠ͳ͍ ● ϑΝΠϧमਖ਼ޙʹࣗಈίϯύΠϧ $ sbt ~run # activator ~run

Slide 42

Slide 42 text

ޓ׵ੑ໰୊ ● Play όʔδϣϯޓ׵ੑ໰୊ ● ։ൃ଎౓͕଎͍ʢϝϦοτͰ΋͋Δʣ ● Ҡߦظؒ͸͘ΕΔ͕ഁյత ● Scala όʔδϣϯޓ׵ੑ໰୊ ● ϚΠφʔόʔδϣϯ͝ͱʹόΠφϦޓ ׵ੑ͕ͳ͍ ● ϥΠϒϥϦʹ PR ૹͬͨΓ fork ͨ͠Γ

Slide 43

Slide 43 text

sbt-web ● grunt/gulp ͷΑ͏ͳϏϧυγεςϜ ● ΤίγεςϜʹ৐ΔͨΊར༻͍ͯ͠ͳ ͍ ● JS ք۾ͷར༻ਓ਺/ϥΠϒϥϦ਺ͷࠩ ● όʔδϣϯΞοϓ໰୊

Slide 44

Slide 44 text

Build front-end with sbt ● ։ൃ࣌͸ sbt ʹλεΫΛ௥Ճͯࣗ͠ಈ Ͱ gulp (npm) Λ࣮ߦ ● https://www.playframework.com/ documentation/2.5.x/SBTCookbook

Slide 45

Slide 45 text

ϑϩϯτΤϯυ໰୊ ● JavaScript/CSS मਖ਼΋ύοέʔδϯά ● Scala ίϯύΠϧ଎౓໰୊ ● ΤϯυϢʔβʔ͸ࠓࠔͬͯΔ ● ࠩ͠໭͠Λ؆୯ʹͰ͖ΔΑ͏ʹ͢Δ ● API αʔόʔͱͯ͠ͷར༻ݕ౼

Slide 46

Slide 46 text

͕͜͜ବ໨ͩΑ Play ·ͱΊ ● ϓϩδΣΫτ͕େ͖͘ͳΔͱίϯύΠϧ ࣌ؒ΋૿Ճ ● ഁյతͳΞοϓάϨʔυ ● อकతͳϓϩδΣΫτͰ͸ޙʑͭΒ͘ ͳΔ ● Play ʹґଘ͗͢͠ͳ͍ ● γεςϜʹݟ߹ͬͨߏ੒Λߟ͑Δ

Slide 47

Slide 47 text

Play Framework ·ͱΊ ● Lightbend ࣾʹΑΔ Scala Web Framework ͷσϑΝΫτ ● τϨϯυΛऔΓೖΕͯ։ൃ͕׆ൃ ● গͳ͘ͱ΋ ̐ ೥͸ܧଓ͓ͯ͠Γɺ 2.6/3.0 ʹ޲͚ͯ։ൃத

Slide 48

Slide 48 text

Play Framework ·ͱΊ ● ܕʹकΒΕͳ͕Βָ͘͠ Web ։ൃ ● খ͍͞ϓϩδΣΫτɺࣾ಺πʔϧͰ࢝ ΊΔ͕Φεεϝ ● Scala ͷػೳΛ͍֮͑ͯ͘ػձʹ΋ ● API αʔόʔͱͯ͠࢖ͬͯΈΔ