Play is a highproductivity Java and Scala web application framework that integrates the components and APIs you need for modern web application development. Play is based on a lightweight, stateless, webfriendly architecture and features predictable and minimal resource consumption (CPU, memory, threads) for highlyscalable applications thanks to its reactive model, based on Akka Streams.
Trang 1Play framework
VinaSaver – Tien Nguyen
2017
Trang 2Play framework - Overview
application development.
memory, threads) for highly-scalable applications thanks to its reactive model, based on Akka Streams.
Trang 3ADVANtages Play Framework
Like many frameworks, Play is based on the MVC model (model, view, controller).
It's really fullstack: can develop a web app, compiler, web server,….
Trang 4Play framework and laravel
functionality of the system without having to custom code)
navigate)
• Auto-compiling (Java doesn’t normally do this but Play has built it in)
Trang 5Environment Setup On local server(1)
1 Create virtual host to run your app by adding following rows to file /etc/httpd/conf/httpd.conf
SBT is an open source build tool for Scala and Java projects, similar to Java’s Maven or Ant.
To install sbt please refer to http://www.scala-sbt.org/
Trang 6Environment Setup On local server(2)
4 Typesafe-activator
Activator is build upon sbt and can do everything that sbt can do, plus more Activator New is a fast way to create new Scala projects from a range of different templates and start building them immediately It replaces the Play command in Play Framework
Install activator
Download activator: wget http://downloads.typesafe.com/typesafe-activator/1.3.2/typesafe-activator-1.3.2-minimal.zip
And add the activator script to your PATH Ex: export PATH=$PATH:/usr/bin/activator-1.3.12/bin/
>activator new [project-name] play-scala
>cd [project-name]
Run project >activator run
or run with port 9500 >activator “run 9500”
Trang 7Deploy On Product Server
1 Using the dist task builds a binary version of your app that you can deploy to a server having Java installation.
>sbt dist
This produces a ZIP file containing all JAR files in target/universal folder of your app.
2 To run the app, unzip the file on target server, then run the script in the bin directory The name of the script is your app name
Trang 8Structure play framework project
Source code includes those important folders and files
1 “app” folder: All scala main code of project is put at here
2 “build.sbt” file: In this file you declare plugins library that using in project
3 “conf” folder: In this folder has 2 important files
- “application.conf”: Set config of all plugins that you declare in build.sbt
- “routes”: Define all application routes
4 “public” folder: Include using css, js, image files in project
Trang 9Mvc in play framework
Trang 10View (1)
Template parameters : A template is like a function, so it needs parameters, which must be declared at the top of the template file
Trang 11<link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/template.css")">
<link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")">
Trang 12Controller (1)
sends back a result which is wrapped into an HTTP Response.
Example :
package controllers
import play.api.mvc._
class Application extends Controller{
def index = Action {
//Return page views/index.scala.html with parameter message : String = “Welcome Play Framework”
Ok(views.html.index(“Welcome Play Framework”))
// Redirect(routes.UsersController.user)
}
}
index.scala.html
@* Get parameters message from controller *@
@(message: String) @main("Welcome to Play") {
@* Using parameter message*@
<h1>@message</h1>
}
Trang 13Controller (2)
Example : Call models/Users
package controllers
import play.api.mvc._
import models.Users // import model Users
class Application extends Controller{
def index = Action {
//Call function getAllUsers() in models/Users
val user = Users.getAllUsers()
val email = “user@gmail.com”
//Return views/user.scala.html with data (user, email_user)
Trang 14 The domain model object layer is a set a Java/Scala classes using all the object oriented features available from the Java/Scala language
Example :
package models
import scalikejdbc._
case class Users(id: Int, name: String, email: String, password: String, api_token: String)
object Users extends SQLSyntaxSupport[Users]{
def findById(id: Int)(implicit s: DBSession = AutoSession): Option[Users] = {
sql"select id,name,email,password,api_token,created_at,updated_at from users where id = ${id} map { rs => Users(rs.int("id"), rs.string("name"), rs.string("email"), rs.string("password"), rs.string("api_token")) }.single.apply()
}
}
Trang 15Example :
GET /login controllers.AuthenicationController.login
POST /login controllers.AuthenicationController.auth
Trang 16• A play.api.mvc.Action is basically a (play.api.mvc.Request => play.api.mvc.Result) function that handles a request and generates a result to be sent to the client Example :
def index = Action {
Ok(“It’s work!”) }
def user = Action {
Redirect(routes.UsersController.user) }
Trang 17Use the ScalikeJDBC library to connect database(MySQL)
Add the MySQL JDBC dependency to the build.sbt file
libraryDependencies ++= Seq( jdbc)
libraryDependencies += "mysql" % "mysql-connector-java" % "5.1.24"
Configuration mysql in conf/ application.conf file
Trang 18libraryDependencies += evolutions
Create evolutions script: The first script is named “1.sql”, the second script “2.sql”,
and so on… and should be located in “conf/evolutions/default”
If you agree with the SQL script, you can apply it directly by clicking on the ‘Apply
evolutions’ button.
# - !Ups CREATE TABLE users (
id int(10) NOT NULL AUTO_INCREMENT, name varchar(255) NOT NULL,
email varchar(255) NOT NULL, password varchar(255) NOT NULL, api_token varchar(60) NOT NULL, created_at timestamp,
updated_at timestamp, PRIMARY KEY (id) );
Trang 19REST API(1)
Method : GET
Step 1: Add url routes
GET /all controllers.UsersController.all()
Step 2: Create function all()
def all() = Action { implicit request =>
implicit val userFormat = Json.format[Users]
val list_user = Users.getAllUsers()
Trang 20REST API(2)
Method : POST
Step 1: Add url routes
POST /test controllers.UsersController.test()
Step 2: Create function test()
def test() = Action.async(parse.urlFormEncoded) { implicit request =>
implicit val userFormat = Json.format[Users]
val email = request.body("email").head
val password = request.body("password").head
val list_user = Users.authenication(email,password)
Future(Ok(Json.obj("success"-> true, "data" -> list_user,
"error" -> "" )
)
)
}
Trang 21Demo App(1)
Step 1: Set application routes
In conf/routes set routes like
GET /login controllers.AuthenicationController.login
POST /login controllers.AuthenicationController.auth
GET /logout controllers.AuthenicationController.logout
GET / controllers.UsersController.index
GET /user controllers.UsersController.user
GET /edit/:id controllers.UsersController.editpage(id: Int)
POST /edit/:id controllers.UsersController.edit(id: Int)
GET /add controllers.UsersController.addpage()
POST /add controllers.UsersController.add()
GET /delete/:id controllers.UsersController.delete(id: Int)After that run command line
> activator run
To see how does it look like.
For more functionalities in this app please refer to source code.
Trang 22Demo App(2)
Create screen login (login.scala.html)
@(message:String)
@page("Login page") {
<div id="dMain" class="">
<div class="article" id="aMainContents">
<div id="dMainColumn">
<div class="dLogOut">@message</div>
<form name="login" action="@routes.AuthenicationController.auth" method="post">
<h2><label for="email">ID</label></h2>
<p><input maxlength="100" id="email" class="fWideM" name="email" type="text" value=""></p>
<h2><label for="password"> パパパパパ </label></h2>
<p><input maxlength="100" id="password" class="fWideM" name="password" type="password" value=""></p>
<p class="pBtnLogin"><input class="btnImg" value=" パパパパ " alt=" パパパパ " id="submit" name="sbm_cnf" type="submit"></p>
Trang 23Demo App(3)
Create Model Users (function authentication, updateApiToken)
case class Users(id: Int, name: String, email: String, password: String, api_token: String)
object Users extends SQLSyntaxSupport[Users]{
def md5(s: String) = {
MessageDigest.getInstance("MD5").digest(s.getBytes).map("%02x".format(_)).mkString
}
def authenication(email: String, password: String)(implicit s: DBSession = AutoSession): Option[Users] = {
sql"select id,name,email,password,api_token,created_at,updated_at from users where email = ${email} and password = ${md5(password)}"
map { rs => Users(rs.int("id"),rs.string("name"),rs.string("email"),rs.string("password"),rs.string("api_token")) }.single.apply()
}
def updateApiToken(id: Int)(implicit s: DBSession = AutoSession):Boolean = {
val api_token:String = System.currentTimeMillis().toString()
val result_query = withSQL { update(Users).set(Users.column.api_token -> md5(api_token)).where.eq(Users.column.id, id) }.update.apply()
if(result_query > 0) return true
else return false
}
}
Trang 24Demo App(4)
Create AuthenicationController
class AuthenicationController extends Controller {
def loginForm = Form(mapping("email" -> text, "password" -> text)
(LoginRequest.apply)(LoginRequest.unapply))
case class LoginRequest(email:String, password:String)
def login() = Action { request =>
val api_token = request.session.get("api_token").getOrElse("")
val id_user = request.session.get("user_id").getOrElse("0")
def auth = Action { implicit request =>
val loginRequest = loginForm.bindFromRequest.get;
handleRespone(loginRequest)
}
def handleRespone(request: LoginRequest): Result = {
val result = Users.authenication(request.email,request.password)
Trang 25Demo App(5)
Screen Login : Login success -> List Users
Trang 26<div id="dMain" class="">
<div class="article" id="aMainContents">
Trang 27Demo App(7)
Create UsersController (controller get list users) and function getAllUsers() in Model Users
class UsersController @Inject() extends Controller {
def user = Action {request =>
val api_token = request.session.get("api_token").getOrElse("")
val id_user = request.session.get("user_id").getOrElse("0")
val email_user = request.session.get("email").getOrElse("")
Trang 28Demo App(8)
Model Update/Add/Delete Users
def update_user(id: Int, name:String,email:String, password:String)(implicit s: DBSession = AutoSession):Boolean = {
val result_query = withSQL { update(Users).set(Users.column.name -> name,Users.column.email -> email,Users.column.password -> md5(password))
where.eq(Users.column.id, id) }.update.apply()
if(result_query > 0) return true
else return false
}
def create(name: String, email: String, password : String)(implicit s: DBSession = AutoSession): Long = {
sql"insert into users(name,email,password) values (${name}, ${email}, ${md5(password)})"
.updateAndReturnGeneratedKey.apply() // returns auto-incremeneted id
}
def deleteUser(id: Int)(implicit s: DBSession = AutoSession):Boolean = {
val result_query = withSQL {
delete.from(Users).where.eq(Users.column.id, id)
}.update.apply()
if(result_query > 0) return true
else return false
}
Trang 29<div class="col-sm-offset-2 col-sm-8">
<button type="submit" class="btn btn-default">Edit</button>
Trang 30case class UserRequest(email:String, username:String, password:String, repassword:String)
def edit(id : Int) = Action { implicit request =>
val id_user = request.session.get("user_id").getOrElse("0")
val email_user = request.session.get("email").getOrElse("")
val editRequest = userForm.bindFromRequest.get;
Trang 31def add() = Action { implicit request =>
val id_user = request.session.get("user_id").getOrElse("0")
val email_user = request.session.get("email").getOrElse("")
val addRequest = userForm.bindFromRequest.get;
def delete(id: Int) = Action {request =>
val api_token = request.session.get("api_token").getOrElse("")
val id_user = request.session.get("user_id").getOrElse("0")