`
sillycat
  • 浏览: 2489239 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

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



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics