中英文对照 介绍Play Framework 框架的控制器(Controller)

红薯 发布于 2010/07/07 17:41
阅读 6K+
收藏 14

下面内容来自 Play 的官方文档中关于控制器一节的内容。

原文:http://www.playframework.org/documentation/1.0.3/controllers
翻译:红薯 (http://my.oschina.net/javayou)
转载请注明出处:开源中国社区(http://www.oschina.net)


Play Framework 框架的控制器(Controller)

Business logic is managed in the domain model layer. As a client (typically a web browser) cannot directly invoke this code, the functionality of a domain object is exposed as resources represented by URIs.

业务逻辑是在域模型层里进行管理,客户端(典型的客户端就是浏览器)无法直接调用业务逻辑代码,客户端是通过资源的URI来访问到域对象。

A client uses the uniform API provided by the HTTP protocol to manipulate these resources, and by implication the underlying business logic. However, this mapping of resources to domain objects is not a bijection: the granularity can be expressed at different levels, some resources may be virtuals, for some resources aliases may be defined…

客户端使用 HTTP 协议中提供的统一方法来访问这些特定资源,并隐式调用底层的业务逻辑。但是这种URI资源到域对象之间的映射关系并不是双向的,其粒度可以使用不同的层次来表示。某些资源可以是虚拟的,也可以给资源定义一个别名…

This is precisely the role played by the Controller layer: providing a glue between the domain model objects and transport layer events. As the Model layer, controllers are written in pure Java, making it easy to access or modify Model objects. Like the HTTP interface, Controllers are procedural and Request/Response oriented.

这正是控制器层所起的作用:提供一个域模型对象与传输层之间的映射关系。由于域模型层和控制器都是纯Java编写的,因此很容易访问或修改模型对象。与HTTP接口类似,控制器是面向过程和请求/响应模型的。

The Controller layer reduces the impedance mismatch between HTTP and the Domain Model.

控制器层可减少由于 HTTP 协议和域模型之间不匹配的障碍。

Note

注意

There are different architectural models with different strategies. Some protocols give you direct access to the domain model objects. This is typically what EJB or Corba protocols do. In these cases, the architectural style used is RPC (Remote Procedure Call). These communication styles are hardly compatible with web architecture.

不同的体系架构有着不同的设计策略,某些协议可以让你直接访问域模型对象,例如 EJB 和 CORBA 协议就是这么做的。在这种情况下,使用的 RPC 远程过程调用的设计风格,这种设计风格很难跟 Web 应用兼容。

Some technologies like SOAP try to give access to the model object domain through the Web. However, SOAP is just another RPC-style protocol, in this case using HTTP as a transport protocol. It is not an application protocol.

而另外一些技术例如 SOAP 试图通过 Web 来访问域对象模型,但不管怎样,SOAP 还是 RPC 风格的设计,尽管使用的是 HTTP 传输协议,这并不是应用的协议。

The web’s principles are not fundamentally object-oriented. So a layer is needed to adapt HTTP to your favorite language.


从根本上来说,Web 的原则并不是面向对象的,因此需要引入一个用来将 HTTP 协议转化为你喜好的编程语言的层,这就是控制层。

A controller overview

控制器概述

A Controller is a Java class, hosted by the controllers package, and subclassing play.mvc.Controller.

在 Play 框架中,控制器其实就是一个 Java 类,位于 controllers 包中,继承了父类 play.mvc.Controller。

This is a Controller:

这里是一个简单控制器的源码:

package controllers;
 
import models.Client;
import play.mvc.Controller;
 
public class Clients extends Controller {
 
    public static void show(Long id) {
        Client client = Client.findById(id);
        render(client);
    }
 
    public static void delete(Long id) {
        Client client = Client.findById(id);
        client.delete();
    }
 
}

Each public, static method in a Controller is called an action. The signature for an action method is always:

在这个示例控制器中,每一个被声明为 public static 的方法被称为 Action,每个 Action 的形式如下所示:

public static void action_name(params...);

You can define parameters in the action method signature. These parameters will be automatically resolved by the framework from the corresponding HTTP parameters.

你可以为 Action 定义各种参数,这些参数会自动与 HTTP 的参数进行绑定和赋值。

Usually, an action method doesn’t include a return statement. The method exit is done by the invocation of a result method. In this example, render(…) is a result method that executes and displays a template.

一般情况下,Action 方法无需返回任何值,该方法通过调用一个结果方法来结束执行,例如 render 就是用来执行并显示一个页面模板。

Retrieving HTTP parameters

获取 HTTP 参数

An HTTP request contains data. This data can be extracted from:

    * The URI path: in /clients/1541, 1541 is dynamic part of the URI Pattern.
    * The Query String: /clients?id=1541.
    * The request body: if the request was sent from an HTML form, the request body contains the form data encoded as x-www-urlform-encoded.


在 HTTP 的请求中包含各种参数数据,例如:

    * URI路径: /clients/1541, 1541 是一种动态的URI路径模式
    * Query String: /clients?id=1541.
    * POST方式的请求,该请求来自某个表单的提交,数据编码方式x-www-urlform-encoded.

In all cases, Play extracts this data and builds a Map<String, String[]> which contains all the HTTP parameters. The key is the parameter name. The parameter name is derived from:

    * The name of the dynamic part of the URI (as specified in the route)
    * The name portion of a name-value pair taken from the Query String
    * The contents of a x-www-urlform-encoded body.


在所有的这些情况中,Play 框架解析出这些数据,并将数据保存在一个 Map<String,String[]> 类型的变量中,Map 的 key 就是参数名,而参数名来自于:

    * routes 中定义的名称,针对于例如 /clients/1541 这种URI请求
    * Query String 中的参数名
    * 来自x-www-urlform-encoded 内容的参数名

Using the params map

使用参数映射

The params object is available to any Controller class (it is defined in the play.mvc.Controller super class). This object contains all the HTTP parameters found for the current request.

For example:


参数对象对所有控制器类都是可访问的,在 play.mvc.Controller 类中定义,该对象包含了当前请求的所有参数。

例如:

public static void show() {
    String id = params.get("id");
    String[] names = params.getAll("names");
}

You can also ask Play to do the type conversion for you:

你也可以让 Play 框架帮你做类型转换:

public static void show() {
    Long id = params.get("id", Long.class);
}

But wait, there are better ways to do this :)

但是等等,别急,还有更好的方法来获取参数 

From the action method signature

You can retrieve HTTP parameters directly from the action method signature. The Java parameter’s name must be the same as the HTTP parameter’s.

For example, in this request:


通过 action 方法

你可以通过 action 方法来直接获取 HTTP 的请求参数,只需要保证 action 方法的参数名和 HTTP 参数名一致即可。

例如下面这样一个请求:

/clients?id=1451

An action method can retrieve the id parameter value by declaring an id parameter in its signature:

要获取这个 id 参数,我们只需要编写如下的 action 方法即可:

public static void show(String id) {
    System.out.println(id);
}

You can use other Java types than String. In this case the framework will try to cast the parameter value to the correct Java type:

我们也可以指定不同的参数类型,而不仅仅是字符串类型,例如下面的代码将参数转成一个 Long 对象,而 Play 框架会自动帮我们实现数据的类型转换:

public static void show(Long id) {
    System.out.println(id); 
}

If the parameter is multivalued, you can declare an Array argument:


如果某个参数有多个值,可用数组来定义该参数:

public static void show(Long[] id) {
    for(String anId : id) {
        System.out.println(id);
    }
}

or even a collection type:

也可以是集合类型,例如 List:

public static void show(List<Long> id) {
    for(String anId : id) {
        System.out.println(id);
    }
}

Exceptions

例外

If the HTTP parameter corresponding to the action method argument is not found, the corresponding method argument is set to its default value (typically null for objects and 0 for primitive numeric types). If a value is found but can’t be properly cast to the required Java type, an error is added to the validation error collection and the default value is used.

如果与 action 方法中的参数没有找到对应的 HTTP 参数,那么 Play 框架会给这个参数设置一个默认值,例如 null 或者数值的 0;但如果action的参数定义为数值类型,而 HTTP 参数确实一个字符串无法转成数值时,那么将会生成一个错误的验证信息,并给这个数值参数设置为默认值

Advanced HTTP to Java binding
Simple types


高级HTTP 到 Java 的绑定
简单类型

All the native and common Java type are automatically bound:

所有 Java 自带的一些简单类型(如下所示),Play 框架都可以实现自动转换:

int, long, boolean, char, byte, float, double, Integer, Long, Boolean, Char, String, Float, Double.

Note that if the parameter is missing in the HTTP Request, or if automatic conversion fails, Object type will be set to null and native types will be set to their default value.

需要注意的是,如果转换失败,那么参数值会设置成默认。

Date

A date object can be automatically bound if the date’s string representation matches one of the following patterns:


日期类型

日期数据支持以下几种格式的自动转换:

    * yyyy-MM-dd’T’hh🇲🇲ss’Z' // ISO8601 + timezone
    * yyyy-MM-dd’T’hh🇲🇲ss" // ISO8601
    * yyyy-MM-dd
    * yyyyMMdd’T’hhmmss
    * yyyyMMddhhmmss
    * dd'/‘MM’/'yyyy
    * dd-MM-yyyy
    * ddMMyyyy
    * MMddyy
    * MM-dd-yy
    * MM'/‘dd’/'yy

For example:

例如:

archives?from=21/12/1980

public static void articlesSince(Date from) {
    List<Article> articles = Article.findBy("date >= ?", from);
    render(articles);
}

Files

文件上传

File upload is easy with Play. Use a multipart/form-data encoded request to post files to the server, and then use the java.io.File type to retrieve the file object:

在 Play 框架中处理文件上传是非常简单的事,一个 multipart/form-data 编码的请求发送到 Play 服务器,Play 框架会自动为该上传文件生成一个 File 对象:

public static void create(String comment, File attachment) {
    String s3Key = S3.post(attachment);
    Document doc = new Document(comment, s3Key);
    doc.save();
    show(doc.id);
}

The created file has the same name as the original file. It’s stored in a temporary directory and deleted at the end of the request. So you have to copy it in a safe directory or it will be lost.

而且File 对象的文件名跟上传文件原来的名称一致,它被存放在临时目录中,一旦请求结束会自动删除,因此如果要长期使用这个文件,请保存到安全的目录。

Arrays or collections of supported types

数组和集合类型

All supported types can be retrieved as an Array or a collection of objects:


所有被支持的类型都可以通过数组或者集合来获取:

public static void show(Long[] id) {
    ...
}

or:

public static void show(List<Long> id) {
    ...
}

or:

public static void show(Set<Long> id) {
    ...
}

POJO object binding

POJO 对象绑定

Play also automatically binds any of your model classes using the same simple naming convention rules.

Play 可自动将模型类与请求参数绑定,绑定的规则是类属性名与参数名一致:

public static void create(Client client ) {
    client.save();
    show(client);
}

A query string to create a client using this action would look like:

?client.name=Zenexity&client.email=contact@zenexity.fr

例如一个用来创建客户的请求链接如:
?client.name=Zenexity&client.email=contact@zenexity.fr

Play creates a Client instance and resolves HTTP parameters name to properties on the Client object. Unresolved parameters are safely ignored. Types mismatches are also safely ignored.

Parameter binding is done recursively, which means you can address complete object graphs:


Play 会自动创建一个 Client 的实例,并将对应的参数赋值给该实例的属性,一些无法解析的参数会被忽略,类型不匹配也会被忽略。

参数绑定是递归执行的,因此你可以使用如下方式定义整个对象的结构:

?client.name=Zenexity
&client.address.street=64+rue+taitbout
&client.address.zip=75009
&client.address.country=France

In order to update a list of model objects, use array notation and reference the object’s ID. For example imagine the Client model has a list of Customer models declared as List customers. To update the list of Customers you would provide a query string like the following:

如果需要更新一组模型对象,可使用数组的方式呈现,例如:

?client.customers[0].id=123
&client.customers[1].id=456
&client.customers[2].id=789

JPA object binding

JPA 对象绑定

You can automatically bind a JPA object using the HTTP to Java binding.

你可以使用 HTTP 到 Java 的绑定来自动绑定一个 JPA 对象。

You can provide the user.id field yourself in the HTTP parameters. When Play find the id field, it loads the matching instance from the database before editing it. The other parameters provided by the HTTP request are then applied. So you can save it directly.

通过在 HTTP 参数中提供 user.id 属性,Play 可以在编辑前,从数据库中加载匹配的实例,然后除 id 外的其他参数将会被更新到数据库中,如下面代码:

public static void save(User user) {
    user.save(); // ok with 1.0.1
}

Result types

控制器执行结果

An action method has to generate an HTTP response. The easiest way to do this is to emit a Result object. When a Result object is emitted, the normal execution flow is interrupted and the method returns.

For example:

Action 方法是需要生成 HTTP 回应内容的,最简单的方法就是直接通过 render 封装一个结果对象。

例如:

public static void show(Long id) {
    Client client = Client.findById(id);
    render(client);
    System.out.println("This message will never be displayed !");
}

The render(…) method emits a Result object and stops further method execution.

Render 方法输送一个结果对象,并停止 action 方法的执行。

Return some textual content

返回一些文本内容

The renderText(…) method emits a simple Result event which writes some text directly to the underlying HTTP Response.

Example:


可使用 renderText 方法来向浏览器返回一些文本内容。

例如:

public static void countUnreadMessages() {
    Integer unreadMessages = MessagesBox.countUnreadMessages();
    renderText(unreadMessages);
}

You can format the text message using the Java standard formatting syntax:


也可以通过 Java 标准的格式化语法来对输出的文本进行格式处理:

public static void countUnreadMessages() {
    Integer unreadMessages = MessagesBox.countUnreadMessages();
    renderText("There are %s unread messages", unreadMessages);
}

Execute a template

执行模板

If the generated content is complex, you should use a template to generate the response content.

如果生成的内容非常复杂,一般我们需要用一个模板文件来处理。

public class Clients extends Controller {
 
    public static void index() {
        render();   
    }
 
}

A template name is automatically deduced from the Play conventions. The default template path is resolved using the Controller and action names.

In this example the invoked template is:


Play 框架的惯例,模板文件名是跟 action 相对应的,默认的对应方式是使用控制器名和 action 名。

在这个例子中,模板名是:

app/views/Clients/index.html

Add data to the template scope

Often the template needs data. You can add these data to the template scope using the renderArgs object:


为模板添加数据

模板文件是需要数据来执行的,我们可以通过 renderArgs 方法来向模板输送对象:

public class Clients extends Controller {
 
    public static void show(Long id) {
        Client client = Client.findById(id);
        renderArgs.put("client", client);
        render();   
    }
 
}

During template execution, the client variable will be defined.

For example:


在模板执行过程中,client这个变量就可以直接使用。

例如:

<h1>Client ${client.name}</h1>

A simpler way to add data to the template scope

You can pass data directly to the template using render(…) method arguments:


另外一种更简单的向模板传递数据的方式是直接通过 render 方法:

public static void show(Long id) {
    Client client = Client.findById(id);
    render(client);   
}

In this case, the variables accessible by the template have the same name as the local Java variables.

使用这种方法,那么模板中可访问的变量跟action方法中的变量名一致。

You can pass more than one variable:

下面代码是向模板传递多个变量:

public static void show(Long id) {
    Client client = Client.findById(id);
    render(id, client);   
}

Important!

这里很重要!

You can only pass local variables in this way.

你只能传递 action 方法类的变量

Specify another template

指定其他的模板

If you don’t want to use the default template, you can specify your own template file during the render(…) call. Just pass it as the render method’s first parameter:

Example:


你可能不想使用默认的模板,那么可通过 render 方法来指定其他模板,例如:

public static void show(Long id) {
    Client client = Client.findById(id);
    render("Clients/showClient.html", id, client);   
}

Redirect to another URL

重定向到其他 URL 地址

The redirect(…) method emits a Redirect event that in turn generates an HTTP Redirect response.

Play 提供了一个 redirect 方法,可以将请求调整到其他的 URL 地址:

public static void index() {
    redirect("http://www.zenexity.fr");
}

Action chaining

Action 链

There is no equivalent to the Servlet API forward. An HTTP request can only invoke one action. If you need to invoke another action, you have to redirect the browser to the URL able to invoke that action. In this way, the browser URL is always consistent with the executed action, and the Back/Forward/Refresh management is much easier.

Action 链与 Servlet API 中的 forward 并不相同,一个 HTTP 请求只能调用一个 action 。如果你需要调用其他的 action ,你必须将浏览器重定向到你想要调用的 action 上。这样后退、前进和刷新操作就会简单很多。

You can send a Redirect response to any action, simply by invoking the action method in a Java way. The Java call is intercepted by the framework and the correct HTTP Redirect is generated.

For example:


你可以重定向到任意一个 action,只需要简单的调用该 action 方法而已,Play 框架会自动将这种形式的调用解析为 HTTP 的重定向。

例如:

public class Clients extends Controller {
 
    public static void show(Long id) {
        Client client = Client.findById(id);
        render(client);
    }
 
    public static void create(String name) {
        Client client = new Client(name);
        client.save();
        show(client.id);
    }
 
}

With these routes:

GET    /clients/{id}            Clients.show
POST   /clients                 Clients.create

    * The browser sends a POST to the /clients URL.
    * The Router invokes the Clients controller’s create action.
    * The action method call the show action method directly.
    * The Java call is intercepted and the Router reverse route generation creates the URL needed to invoke Clients.show with an id parameter.
    * The HTTP Response is 302 Location:/clients/3132.
    * The browser then issues GET /clients/3132.
    * …

Interceptions

拦截

A controller can define interception methods. Interceptors are invoked for all actions of the controller class and its descendants. It’s a useful way to define treatments that are common to all actions: verifying that a user is authenticated, loading request-scope information…

可以为控制器编写拦截方法,拦截器将在 action 执行的前后被调用。这个用来做用户权限的验证非常有用。

These methods have to be static but not public. You have to annotate these methods with a valid interception marker.
@Before


首先确保拦截器的方法不能定义为 public 但必须是 static 。然后可以通过 @Before 来声明这是一个拦截器方法。

Methods annotated with the @Before annotation are executed before each action call for this Controller.

被声明为 @Before 的方法将会在每个 action 方法被调用之前先执行。

So, to create a security check:

因此,要创建一个权限检查的拦截器如下代码:

public class Admin extends Application {
 
    @Before
    static void checkAuthentification() {
        if(session.get("user") == null) login();
    }
 
    public static void index() {
        List<User> users = User.findAll();
        render(users);
    }
 
    ...
 
}

If you don’t want the @Before method to intercept all action calls, you can specify a list of actions to exclude:

如果你不想拦截所有的 action 方法,那么可以指定不拦截哪些方法:

public class Admin extends Application {
 
    @Before(unless="login")
    static void checkAuthentification() {
        if(session.get("user") == null) login();
    }
 
    public static void index() {
        List<User> users = User.findAll();
        render(users);
    }
 
    ...
 
}

@After

Methods annotated with the @After annotation are executed after each action call for this Controller.

与 @Before 相反,@After 注释用来声明 action 结束调用的拦截器:

public class Admin extends Application {
 
    @After
    static void log() {
        Logger.info("Action executed ...");
    }
 
    public static void index() {
        List<User> users = User.findAll();
        render(users);
    }
 
    ...
 
}

@Finally

Methods annotated with the @Finally annotation are executed after each action result is applied from for this Controller.

@Finally 拦截器声明用来定义一个方法在结果已经生成完成后执行:

public class Admin extends Application {
 
    @Finally
    static void log() {
        Logger.info("Response contains : " + response.out);
    }
 
    public static void index() {
        List<User> users = User.findAll();
        render(users);
    }
 
    ...
 
}

Controller hierarchy

控制器的层次结构

If a Controller class is a subclass of another Controller class, interceptions are applied to the full Controller hierarchy.

如果一个控制器类是另外一个的之类,那么该类中定义的所有拦截器都会影响它所有的子类。

Adding more interceptors using the @With annotation

可使用 @With 注释来增加更多的拦截器

Because Java does not allow multiple inheritance, it can be very limiting to rely on the Controller hierarchy to apply interceptors. But you can define some interceptors in a totally different class, and link them with any controller using the @With annotation.

Example:

因为 Java 不支持多重继承,这对控制器层次是限制很大的,但你可以通过定义一些拦截器,然后使用 @With 注释来声明。

例如:

public class Secure extends Controller {
   
    @Before
    static void checkAuthenticated() {
        if(!session.containsKey("user")) {
            unAuthorized();
        }
    }
}   

And on another Controller:

@With(Secure.class)
public class Admin extends Application {
   
    ...
    
}

Session and Flash scope

会话和闪屏

If you have to keep data across multiple HTTP Requests, you can save them in the Session or the Flash scope. 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.

如果你需要在多个 HTTP 请求间保持数据,那么可以将数据保存在Session 或者是 Flash(闪屏)中。保存在 Session 中的数据在整个用户会话中都是有效的,而 Flash 就只对下一个请求有效。

It’s important to understand that Session and Flash data are not stored in the server but are added to each subsequent HTTP Request, using the Cookie mechanism. So the data size is very limited (up to 4Ko) and you can only store String values.


特别特别需要注意的时,与 J2EE 的做法不同的是,存放于 Session 和 Flash 的数据是通过 Cookie 保存在浏览器的,因此数据大小不能超过4k,而且只能存储字符串。

译者注:千万不要保存敏感数据。

Of course, cookies are signed with a secret key so the client can’t modify the cookie data (or it will be invalidated). The Play session is not aimed to be used as a cache. If you need to cache some data related to a specific session, you can use the Play built-in cache mechanism and use the session.getId() key to keep them related to a specific user session.

当然了,cookies 是通过安全方式进行签名的,因此客户端是无法修改这个数据,只能使之无效。Play 框架的 Session 不能当作是缓存来使用,如果你需要为某个Session缓存某些数据,那么可以使用 session.getId() 来作为缓存的key。

Example:

示例:

public static void index() {
    List messages = Cache.get(session.getId() + "-messages", List.class);
    if(messages == null) {
        // Cache miss
        messages = Message.findByUser(session.get("user"));
        Cache.set(session.getId() + "-messages", messages, "30mn");
    }
    render(messages);
}

The cache has different semantics than the classic Servlet HTTP session object. You can’t assume that these objects will be always in the cache. So it forces you to handle the cache miss cases, and keeps your application fully stateless.


这个缓存在语义上跟 Servlet 的 HTTP Session 是不同的,你不能猜想说缓存中的数据是会一直存在的,因此你需要处理缓存数据失效的情况,使你的应用真正的无状态化。

加载中
0
JavaGG
JavaGG

这么长~~~~~~~~~~~

0
老枪
老枪

巨著呀~

0
walter
walter

可以收藏吗?

0
穿越星辰
穿越星辰

翻译的不错。

0
Sephiroth
Sephiroth

最近Play在社区貌似很火啊~~~

0
开源中国隔壁老王
开源中国隔壁老王

这个貌似不错 我试用了一下

0
徐小路
徐小路

前途不可限量,,,呵呵

0
l
lyuehh

概述这一章(第一次翻译,翻译的不好还请见谅).


Play框架概述

h1. Play framework overview

Play框架是臃肿的企业级Java之外的另一个选择,它关注的是开发的效率和提供REST式的架构风格,
Play是“敏捷软件开发”的绝佳伴侣。

The Play framework is a clean alternative to bloated Enterprise Java stacks. It focuses on developer productivity and targets RESTful architectures. Play is a perfect companion to *agile software development*.

Play框架的目标是使用Java进行快速的web项目开发,让我们看一下它是怎么做到的。
The Play framework’s goal is to ease web applications development while sticking with Java. Let’s see how this is possible.

想看一些代码?
p(note). **Wanna see some code?**

查看“你可以使用Play做的5件最酷的事”:5thinds,或者直接跳至“hello world 实例”:firstapp
Check "Five cool things you can do with play":5things, or start directly with the "hello world tutorial":firstapp.

一个不会让你感觉Java麻烦的java框架
h2. <a name="java">A Java framework without the pain</a>

Play是一个使用纯Java开发的框架,它可以让你继续使用你喜欢的开发环境或类库。如果你已经是一个Java平台的开发者,
那么你不需要切换到另一种语言,其他IDE或者其他类库,只是切换到了另一个更有效率的java环境。
Play is a pure Java framework and allows you to keep your preferred development tools and libraries. If you already use Java as a development platform you don’t need to switch to another language, another IDE and other libraries. *Just switch to a more productive Java environment!*

修改bug,然后Play会自动载入
h2. <a name="reload">Fix the bug and hit Reload</a>

Java平台在开发效率方面已经是声名狼藉了,可能的原因就是重复 “编译-打包-部署”的循环。
The Java platform is infamous for its low productivity, mainly due to repeated and tedious compile-package-deploy cycles.

这就是为什么我们重新考虑开发周期,让使用Play开发变得更有效率。
That’s why we rethought the development cycle to make developing with Play an efficient process.

框架自动编译Java源代码,然后直接热加载到JVM中而不需要重启服务器,你可以编辑,重新加载
然后直接看到修改后的结果,就像在LAMP或者Rails环境中一样。
The framework compiles your Java sources directly and hot-reloads them into the JVM without the need to restart the server. You can then edit, reload and see your modifications immediately, just as in a LAMP or Rails environment.

而且更有趣的是你按自己的爱好,仅仅使用一个简单的文本编辑器而避免使用全功能的Java IDE。
It’s so fun that you can even work with a simple text editor and skip a full-featured Java IDE if you want.

!images/editor!

当有错误发生时,框架努力辨别,然后直接显示出你的错误。
Whenever an error occurs, the framework makes its best effort to identify and show you the problem.

!images/guide1-3!

//下面一句不太好翻译啊
甚至堆栈被分析优化使错误更容易的被解决,看模板执行时如何完美地指出错误所在地的.
Even the stack traces are stripped down and optimized to make it easier to solve problems. Look how template execution is nicely integrated to the Java stack trace.

!images/stacktrace!

简单的无状态的MVC架构
h2. <a>Simple stateless MVC architecture</a>

你一边有一个数据库另一边有一个浏览器,为什么你要在此之间需要一个状态呢?
You’ve got a database on one side and a web browser on the other. Why should you have a state in between?

以有状态和组件式为基础的Java web框架使之容易的自动保存页面状态,但是这带来了很多其他问题,如果用户
打开了第二个窗口时会发生什么,如果用户单击了浏览器的后退按钮呢?
Stateful and component based Java Web frameworks make it easy to automatically save page state, but that brings a lot of other problems: what happens if the user opens a second window? What if the user hits the browser back button?

PHP,Ruby on Rails和Django等许多web应用框架促进了“无共享”架构。
随着浏览器越来越强大,现在很容易使用Ajax,或者离线存储去解决客户端的状态问题。
The "Share Nothing":http://zef.me/883/the-share-nothing-architecture architecture is promoted by many Web application frameworks from PHP to Ruby on Rails or Django. As the browser is becoming more and more powerful, it is now easy to use Ajax or offline storage to solve the state problems client-side.

我们不需要再去hack HTTP模型,在web上重建一个虚假的状态。另一方面,
“无共享”使渲染局部页面,相似的页面,或者部分页面更新变的更容易。
We don’t need to hack the HTTP model anymore to rebuild a fake state over the Web. Another aspect of ‘share nothing’ is to make it easier to render portions of the page in parallel, and to do partial page updates (or progressive enhancements).

HTTP到代码映射
h2. <a name="http">HTTP-to-code mapping</a>

如果你已经使用了另外一种Java web框架,例如Servlet API或者Struts框架,你已经使用了把HTTP协议和Java API抽象的联系起来的奇怪的观念。(好难翻译啊)
我们不是这么想的。一个web应用框架应该给你完全的,直达的对Http进行操作,这是Play和其他Java web框架的一个根本不同。
If you’re already using another Java Web framework like the Servlet API or the Struts framework, you have already used an abstract view of the HTTP protocol with strange Java APIs and concepts. We think differently. A Web application framework should give you full, straightforward access to HTTP and its concepts. This is a fundamental difference between Play and other Java web application frameworks.

Http,Request,Response,REST架构,类型识别,URI都是Play框架主要的思想。
HTTP, the Request/Response pattern, the REST architectural style, content-type negotiation, URI are all major concepts for the Play framework.

例如,绑定一个URI 参数 到Java中调用就像下面一样
For instance, binding a URI pattern to a Java call is just one line:

bc. GET    /clients/{id}        Clients.show
如果Ajax,REST和在页面之间维护前进、后退操作是你每天开发web项目时都会遇到的问题,那么请尝试一下play吧。
If Ajax, REST and managing back/forward movement between web pages are some of the issues you face in your day-to-day web development, just give Play a try.


高效的模板引擎
h2. <a name="templates">Efficient templating engine</a>

我们很喜欢JSP和JSTL表达式语。但是为什么我们需要这么多的配置文件去创建一个标签库,为什么我们不能对象模型进行完全的接触呢?(有点别扭)
jSP有很多的限制也是令人沮丧的原因。这就是为什么我们需要创建一个通用的模板系统,由JSP激发的灵感,但是没有它的限制。
We like the idea behind JSP & Expression Language. But why do we need so many configuration files to create a tag library? Why can’t we have full access to the underlying object model? JSP has a lot of limitations and this is indeed frustrating. That’s why we’ve created a custom template system, inspired by JSP but without its constraints!

你和其他人可能会疲倦的写类似这样的代码
You and anyone else should be tired of writing things like this:

bc. <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
 
<c:choose>
    <c:when test="${emails.unread != null && fn:size(emails.unread)}">
        You have ${fn:size(emails.unread)} unread email(s)!
    </c:when>
    <c:otherwise>
        You have no unread emails!
    </c:otherwise>
</c:choose>

我们认为你应该更倾向于这样写
We think you would certainly prefer to write:

bc. You have ${emails.unread ?: 'no'} ${emails.unread?.pluralize('email')} !
Play模板使用的 表达式语言是Groovy,它和Java语法一致,
Play使用这些模板系统区渲染HTML请求,你可以使用它去产生其他格式的文档例如 email信息,JSON输出等。
The expression language used by the play template engine is "Groovy":http://groovy.codehaus.org/, which provides a syntax consistent with Java. While Play mainly uses the templating system to render HTML responses, you are free to use it to generate any other documents such as e-mail messages, JSON responses, etc.

JPA绑定
h2. <a>JPA on steroids</a>

JPA是一个Java的ORM框架,如果你已经知道它的话,你会惊讶于它和Play的集成。
不需要任何配置,Play会自动启动JPA实体管理器,并神奇的同步,在代码重新载入时。
The Java Persistence API (JPA) is the cleanest object-relational mapping ORM) API available for Java. If you already know it you will be amazed how much simpler it becomes with Play. With nothing to configure, Play will automatically start the JPA Entity Manager and magically synchronize it while the code is reloaded.

而且如果你使用提供的 **play.db.jpa.Model** 超类时,它会帮助你 把代码变的更漂亮。来看一下。
Moreover if you use the provided **play.db.jpa.Model** superclass it will help make your code prettier. Have a look:

bc. public void messages(int page) {
    User connectedUser = User.find("byEmail", connected());
    List<Message> messages = Message.find(
        "user = ? and read = false order by date desc",
        connectedUser
    ).from(page * 10).fetch(10);
    render(connectedUser, messages);
}

测试驱动开发(如果你喜欢它的话)
h2. <a>Test driven development (if you like it)</a>

集成的测试可以让你更容易的去进行测试驱动开发,你可以写下所有类型的测试,从简单的集成测试到完整
的acceptance 测试,然后直接在浏览器中使用Selenium运行。代码覆盖率也会考虑到。
The integrated test runner makes it easy for you do test-driven development (TDD). You can write all kinds of tests, from simple unit tests to full acceptance tests, and run them directly in a browser using "Selenium":http://seleniumhq.org/. Code coverage is also measured.

!images/guide2-2!

全栈的应用开发框架
h2. <a name="full-stack">Full-stack application framework</a>

Play框架的灵感来自我们自己的Java应用,它包含了创建现代 web应用所需的一切。它包含:
通过JDBC的关系数据库支持
使用hibernate管理对象关系映射(使用了JPA API)
集成的缓存支持,容易使用的分布式缓存系统(如果需要的话)
使用JSON和XML的简单web service(我们说的是’真正‘的web service,不是SOAP)
支持使用OpenID进行分布式的身份认证
你的web 应用可以部署到任何支持的地方(应用服务器,GAE,云等)
图形操作API

The Play framework was initially inspired by our own Java applications. It has all the tools needed to create a modern web application, including:

* relational database support through JDBC.
* object-relational mapping using Hibernate (with the JPA API).
* integrated cache support, with easy use of the distributed memcached system if needed.
* straightforward web services consumption either in JSON or XML (we are talking *real* web services here; not the SOAP stuff).
* OpenID support for distributed authentication.
* your web application ready to be deployed anywhere (application server, Google App Engine, Cloud, etc…)
* image manipulation API.

Play模块化的结构使你可以把web 应用和其他结合在一起,感谢模块,你可以以一种非常简单的方式重用你的Java 代码,
模板,静态资源(如JavaScript和CSS文件等).
The modular architecture lets you combine a web application with many others. Thanks to "application modules":modules, you can reuse your Java code, templates and static resources (such as JavaScript and CSS files) in a simple way.

请尝试一下吧
p(note). **Give it a try**
 
 安装、启动你的第一个应用
"Install the Play framework":install and start developing your first application.

0
OTooo
OTooo

建议弄个SVN,直接在源码上翻译。

这样不管是翻译人员,还是看的人都更方便吧。

以后更新也方便。

0
该用户已被和谐
该用户已被和谐

http://blog.csdn.net/treesky/archive/2010/10/12/5936320.aspx

  1. public static void fileupload(File attachment){  
  2.     if(request.method.equalsIgnoreCase("GET")){  
  3.         render();  
  4.     }else{  
  5.         Files.copy(attachment, Play.getFile("public/attachment/"+attachment.getName()));  
  6.         render();  
  7.     }  
  8. } //文件上传的一段
返回顶部
顶部