Playframework(7)Scala Project and HTTP Programming

Playframework(7)Scala Project and HTTP Programming

1. HTTP Programming
1.1 Actions, Controllers and Results
play.api.mvc.Result function that handles a request and generates a result to be sent to the client.
val echo = Action{ requets =>
Ok("Got request [" + request + "]")
}

Building an Action
Action {
Ok("Hello World")
}

That is the simple action, but we can not get a reference to the incoming request.
So there is another Action Builder that takes as an argument a function
Action { request =>
Ok("Got request [ " + request + "]")
}

Action(parse.json) { implicit request =>
Ok("Got request [ " + request + "]")
}
We specify an additional BodyParser argument.

Controllers are action generators
A Controller is nothing more than a singleton object that generates Action values.

object Application extends Controller {
def index = Action {
Ok("It works!")
}
}

Of course, the action generator method can have parameters, and these parameters can be captured b the Action closure:
def hello(name: String) = Action {
Ok("Hello " + name)
}

Simple Results
An HTTP result with a status code, a set of HTTP headers and a body to be sent to the web client. These results are defined by play.api.mvc.SimpleResult
def index = Action {
SimpleResult(
header = ResponseHeader(200, Map(CONTENT_TYPE -> "text/plain")),
body = Enumerator("Hello world!");
)
}

Ok is the helper to create common results. Ok("Hello world!")

Here are several examples to create various results:
val ok = Ok("Hello world!")
val notFound = NotFound
val pageNotFound = NotFound(<h1>Page not found</h1>)

val badRequest = BadRequest(views.html.form(formWithErrors))
val oops = InternalServerError("Oops");
val anyStatus = Status(488)("Strange response type!")

Redirects are simple results too
def index = Action{
Redirect("/user/home")
}

The default is using a 303 SEE_OTHER response type.
def index = Action{
Redirect("/user/home", status = MOVED_PERMANENTLY) // permanently
}

"TODO" dummy page
def index(name: String) = TODO

1.2 HTTP routing
The built-in HTTP router
An HTTP request is seen as an event by the MVC framework. This event contains 2 major pieces of information:
the request path, including the query string (e.g. /clients/1542, /photos/list)
the HTTP method (e.g. GET, POST, …)

The routes file syntax
HTTP method URI pattern a call to an Action generator
GET /clients/:id controllers.Clients.show(id:Long)

The HTTP method
GET, POST, PUT, DELETE, HEAD

The URI pattern

Static path
GET /clients/all controllers.Clients.list()

Dynamic parts
GET /clients/:id controllers.Clients.show(id: Long)

Dynamic parts spanning several /
GET /files/*name controllers.Application.download(name)

Here for a request like GET /files/images/logo.png, the name dynamic part will capture the images/logo.png value.

Dynamic parts with custom regular expressions
GET /clients/$id<[0-9]+> controllers.Clients.show(id: Long)

Call to the action generator method
controllers.Application.show(page)

Parameter types
GET /client/:id controllers.Clients.show(id: Long)

Parameters with fixed values
GET / controllers.Application.show(page="home")

Parameters with default values
GET /clients controllers.Clients.list(page: Int ?= 1)

Routing priority
Many routes can match the same request. If there is a conflict, the first route (in declaration order) is used.

Reverse routing
GET /hello/:name controllers.Application.hello(name)

def helloBob = Action{
Redirect(routes.Application.hello("Bob"))
}

1.3 Manipulating Result
Changing the default Content-Type
val textResult = Ok("Hello World!") will automatically set the Content-Type header to text/plain, while:

val xmlResult = Ok(<message>Hello World!</message)
will set the Content-Type header to text/xml.

That will happen automatically, but sometimes, we want to control that. We can use as(newContentType) method on a result to create a new similar result with a different Content-Type header:
val htmlResult = Ok(<h1>Hello World!</h1).as("text/html")

or even better, using:
val htmlResult = Ok(<h1>Hello World!</h1>)as(HTML)

Manipulating HTTP Headers
Ok("Hello World!").withHeaders(
CACHE_CONTROL -> "max-age=3600",
ETAG -> "xx"
)

Setting and discarding cookies
Ok("Hello world").withCookies(
Cookie("theme", "blue")
)

Ok("Hello world").discardingCookies("theme")

Changing the charset for text based HTTP response
implicit val myCustomCharset = Codec.javaSupported("iso-8859-1")

1.4 Session and Flash Scopes
The same as java play, data stored in the Session are available during the whole user Session, and data stored in the Flash scope are available to the next request only.

Reading a Session value
def index = Action { request =>
request.session.get("connected").map{ user =>
Ok("Hello " + user)
}.getOrElse{
Unauthorized("Oops, you are not connected")
}
}

Alternatively you can retrieve the Session implicitly from a request:
def index = Action { implicit request =>
session.get("connected").map{ user =>
Ok("Hello " + user)
}.getOrElse{
Unauthorized("Oops, you are not connected")
}
}

Storing data in the Session
Ok("Welcome!").withSession(
"connected" -> "user@gmail.com"
)

This method will replace the whole session. If we only need to add an element to an existing Session, just add an element to the incoming session.
Ok("Hello World!").withSession(
session + ("saidHello" -> "yes" )
)

Discarding the whole session
Ok("Bye").withNewSession

Flash Scope
The flash scope works exactly like the Session, but with two differences:
data are kept for only one request
the Flash cookie is not signed, making it possible for the user to modify it.

The flash scope data are just kept for the next request and because there are no guarantees to ensure the request order in a complex Web application, the flash scope is subject to race conditions.

def index = Action { implicit request =>
Ok{
flash.get("success").getOrElse("Welcome!")
}
}

def save = Action{
Redirect("/home").flashing(
"success" -> "The item has been created"
)
}

References:
http://www.playframework.org/documentation/2.0.4/ScalaHome
http://www.playframework.org/documentation/2.0.4/ScalaActions
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值