日期:2014-05-20  浏览次数:20901 次

Playframework(3)Java Project and Handling asynchronous results
Playframework(3)Java Project and Handling asynchronous results
2. Handling asynchronous results
We were able to compute the result to send to the web client directly. This is not always the case: the result may depend of an expensive computation or on a long web service call.

Action should be as fast as possible. (non blocking). We should return a result if we are not yet able to compute, the response should be a promise of a result.

Promise<Result> instead of a normal Result.

Play will then serve this result as soon as the promise is redeemed.
The web client will be blocked while waiting for the response but nothing will be blocked on the server, and server resources can be used to serve other clients.

How to create a Promise<Result>

I am not quite understand this part. Maybe, I will learn it later.

Streaming HTTP responses
According to HTTP 1.1, the server must send the appropriate Content-Length HTTP header along with the response.
public static Result index(){
     return ok("Hello World")
}
Play is able to compute the content size for us and generate the appropriate header.

Serving Files
sending back a local file
…snip…
return ok(new java.io.File("/tmp/fileToServe.pdf"));
…snip...
The default Content-Dispostion will be Disposition: attachment; filename=fileToServe.pdf

Chunked Response
Chunked transfer encoding, dynamically-computed content with no content size available.
public static index(){
     Chunks<String> chunks = new StringChunks(){
          public void onReady(Chunks.Out<String> out){
               registerOutChannelSomewhere(out);
          }
     }
     ok(chunks);
}
public void registerOutChannelSomewhere(Chunks.Out<String> out){
     out.write("kiko");
     out.write("foo");
     out.close();
}
HTTP/1.1 200 OK    Content-Type: text/plain; charset=utf-8    Transfer-Encoding: chunked

Comet Sockets and WebSockets
play is able to handle these things. But I will learn them in the future.

3. The template engine
A Play Scala template is a simple text file that contains small blocks of Scala code. Templates can generate any text-based format, such as HTML, XML or CSV.

Templates are compiled as standard Scala functions, following a simple naming convention. If you create a
views/Application/index.scala.html
views.html.Application.index
class that has a render() method.

For example, template:
@(customer: Customer, orders: List[Order])
<h1>Welcome @customer.name!</h1>
<ul>
@for(order <- orders){
     <li>@order.getTitle()</li>
}
</ul>

Content html = views.html.Application.index.render(customer, orders);

Escape the special character like this @@.

@customer.getName()!    @customer.name! @(customer.getFirstName() + customer.getLastName())!
@{var name= customer.getFirstName() + customer.getLastName(); name}!    // multiple statements

Template parameters
A template is like a function, so it needs parameters, which must be declared at the top of the template file:
@(customer: models.Customer, orders: List[models.Order])
@(title: String = "Home")        //default value
@(title:String)(body: Html)     //several parameters

Iterating
<ul>
@for(p <- products){
     <li>@p.getName() ($@p.getPrice())</li>
}
</ul>

If-blocks   simply use Scala's standard if statement
@if(items.isEmpty()){
     <h1>Nothing to display</h1>
}else{
     <h1>@items.size() items!</h1>
}

Declaring Reusable Blocks
We can create reusable code blocks:
@display(product:models.Product) = {
     @product.getName() ($@product.getPrice())
}

<ul>
@for(product <- products){
     @display(product)
}
</ul>

Comments
@*  coments here *@

Escaping
Dynamic content parts are escaped according to the template type's rules(e.g. HTML or XML). If we want to output raw content fragment.
<p>
@Html(article.content)
</p>

Common Template Use Cases
Layout ---- views/main.scala.html
@(title: String)(content: Html)
<!DOCTYPE html>
<html>
     <head>
          <title>@title</title>
     </head>
     <body>
          <section class="content">@content</section>
     </body>
</html>

Out simple page can use this template views/Application/index.scala.html
@main(title = "Home"){
     <h1>Home page</h1>
}

Add a second page-specific content block for a sidebar or breadcrumb trail.
@(title: String)(sidebar: Html)(content: Html)
<!DOCTYPE html>
     <head>
          <title>@title</title>
     </head>
     <body>
          <section class="content">@content</section>
          <section class="sidebar">@sidebar</section>
     </body>
</html>

Our page template will be:
@main("Home"){
     <h1>Sidebar</h1>
}{
     <h1>Home page</h1>
}

Or we can declare the sidebar block separately:
@sidebar = {
     <h1>Sidebar</h1>
}

@main("Home")(sidebar) {
     <h1>Home page</h1>
}

Tags
views/tags/notice.scala.html
@(level: String = "error") (body: (string) => Html)
@level match{
     case "success" =>{
          <p class="success">
               @body("green")
          </p>
     }

     case "error" => {
          <p class="error">
               @body("red")
          </p>
     }
}

When we use the tag:
@import tags._
@notice("error"){ color =>
     Oops, something is <span style="color:@color">Wrong</span>
}


References:
http://www.playframework.org/documentation/2.0.4/JavaAsync
http://www.playframework.org/documentation/2.0.4/JavaHome