Play 2.0 中文资料 - 会话和 Flash 域

会话和 Flash 域在 Play 中有何不同

如果你不得不要跨多个 HTTP 请求来保存数据, 你可以存在会话或是 Flash 域中. 存储在会话中的数据在整个会话期间可用, 而存储在 Flash 域中数据只对下一次请求有效.

理解到会话和 Flash 数据不是由服务器来存储,而是以 Cookie 机制添加到每一次后续的 HTTP 请求是很重要的. 这也就意味着数据的大小是很受限的 (不到 4 KB) ,而且你只能存储字符串.

当然了, Cookie 值是由密钥签名了的,这使得客户端不存修改 Cookie 数据(或者说这样做会让它失效).

Play 会话不能当成缓存来用.  假如你需要缓存与某一会话相关的数据, 你可以使用 Play 内置的缓存机制并存储一个唯一的 ID 在用户会话中与之关联.

会话没有技术上的超时控制. 它在用户关闭 Web 浏览器后就会过期. 如果你的应用需要一种功能性的超时控制, 那就在用户会话中存储一个时间戳,并在应用需要的时候用它 (例如: 最大的会话持续时间, 最大的非活动时间, 等等.).

读取会话值

你可以从 HTTP 请求中获取传入的会话: 阅读全文 >>

Play 2.0 中文资料 - 剖析 Play 2.0 应用

标准的应用目录布局

Play 应用的目录布局是标准化的,这样可保持尽量的简单. 一个标准的 Play 应用看起来如下:

阅读全文 >>

Play 2.0 中文资料 - 创建一个新的应用

用 play 命令创建一个应用

创建一个新应用最初的方式是用 play new 命令.

这会询问你一些信息.

  • 应用的名称 (仅用于显示, 这个名称后面将在几个消息中使用到).
  • 用于这个应用的模板. 你可以从 默认的 Scala 应用, 默认的 Java 应用, 和 空应用 三个选项目中选择.

Unmi 注: 新版 play new 命令允许你带上目录名,让你在指定的目录下创建应用,在 2.0-beta 版中,只是在当前目录下创建你的应用。运行 play help 看显示的 new 是否是: new [directory]    Create a new Play application in the specified directory. 就知道能否指定应用的目录。

并且此时的 play new 命令可以用

这样就会在 ~/Desktop/unmi 目录中创建应用,后面的提示是一样的. 在 ~/Desktop/unmi 目录下有应用所需的 app, conf, public 等目录。
阅读全文 >>

Play 2.0 中文资料 - 安装

系统要求

为了运行 Play 框架, 你需要 JDK 6 或更新的版本.

假如你正使用 MacOS, Java 已经内置了. 如果你正在使用 Linux, 请确认使用了 Sun  的 JDK 或 OpenJDK (不是 gcj, 它是许多 Linux 发行版的默认  Java 命令). 要是用的是 Windows, 只下载安装最新版的 JDK 安装包即可.

确可 javajavac 命令被设置到了当前路径下 (你可以在命令行提示符下通过输入 java -versionjavac 来检查它).

下载二进制包

下载 Play 2.0 的二进制包 (选择最新的 2.0 RC 版) 并解压到有读和写权限的目录下. (运行 play 会向安装目录中写入文件, 所以不要安装在 /opt, /usr/local 或任何你无需设置写入权限的目录中.)

Unmi 注: 当前最新的版本是 2.0.4。 阅读全文 >>

Play 2.0 中文资料 - 开篇

Play 当前版本是 2.0.4,2.0 前的版本通常会称为 PlayFramework,或者 Play!,现在干脆直呼为 Play 了,名气大了些就这样的,似乎越来越显得不可一世了。本人有意更深点了解 Play 框架,所以打算翻译官网 Manual, tutorials & references 一系列资料,并且着重点会先放在基于 Scala 语言的 Play 2.0 的应用。

Play 2.0 是一个高生产率的 Java 和 Scala 的 Web 应用框架,它集成了现代 Web 应用开发所而的组件和 API。

Play 是轻量级的,无状态的,Web 友好的架构,并且是特征可预期的(features predictable)。还借助于它的反应模型(reactive model) 和 Iteratee IO 的使用,让 Play 为高伸缩性的应用最小化了资源消耗(CPU, 内存和线程).

Unmi 注:关于 Iteratee IO, 可参考:Iteratee I/OScalaz Tutorial: Enumeration-Based I/O with Iteratees

第一步要翻译的内容只想覆盖到以下:

开始使用

Scala 用元组/列表类型实现多返回值的函数

Java 的方法不支持多返回值,或者我们想达到返回多个值的效果时,不得不借用数组、列表或对象等来容纳多个值返回给调用者。这样使用起来不怎么优美,特别是为返回多个值而创造一个类成本有点高,如果 Java 也存在像 C# 那样的匿名类倒好。C# 如何使用匿名类返回多个值可参看本文后面的例子。

把 Scala 当作是一种脚本语言,它的灵活性就应该与 Perl 或 Ruby 看齐。Scala 的方法也可以有多个返回值,它实现些种行为,可借助于元组和列表类型,虽然你也可以发掘更多的实现方式,但到目前为止,我还是觉得用元组和列表最简单。

下面给出代码例子,让我们瞧瞧 Scala 如何实现方法多个返回值,并且作为对比我还会贴上 Perl, Ruby 和 C# 可以怎么实现多返回值。我是 Java 的惯用者,不过我一直都未否认,从语言层面 C# 比 Java 要显得优雅的多。

用元组实现 Scala 方法多返回值:

方法返回一个元组,里面可以组合任何多个的不同类型的返回值,调用时可以用元组变量或元组模式去接收方法的返回值,用元组模式的方式更好看些,也才能算作真正的多返回值。 阅读全文 >>

Scala 无参数方法和统一访问原则

在 Scala 中当方法不需要接受参数时可定义成两种类型的方法

1.  def width(): Int   空括号方法(empty-paren method)

2. def width: Int  无参数方法(parameterless method)

从语法上讲,Scala 在调用上面那种类型的方法时都可以统一用 obj.width 的方式,实际对于无参数方法是只能用 obj.width 的方式,而空括号方法,既可以用 obj.width 也可以用 obj.width() 的形式。

那么 Scala 在方法无须参数时是定义空括号方法还是无参数方法时有什么约定呢?

当方法没有副作用(side effect)时,定义成无参数方法;当方法会产生副作用时,定义成空括号方法

那么又该如何识别方法是否有副作用呢?一般来说有副作用的地方会在于其结果类型是否为 Unit。如果某个函数不返回任何有用的值,也就是说如果返回类型为 Unit,那么这个函数唯一能产生的作用就只能是产生某种副作用,例如改变对象内部的某种状态,或是向控制台的输出等。有副作用的方法就像是数据库的存储过程(一般用于更新数据),无副作用的方法像是数据库的函数(一般用于查询得到数据)。 阅读全文 >>

Scala 的 apply 和 update 方法的应用

Scala 是构建在 JVM 上的静态类型的脚本语言,而脚本语言总是会有些约定来增强灵活性。灵活性可以让掌握了它的人如鱼得水,也会让初学者不知所措。比如说 Scala 为配合 DSL 在方法调用时有这么一条约定:

在明确了方法调用的接收者的情况下,若方法只有一个参数时,调用的时候就可以省略点及括号。如 “0 to 2”,实际完整调用是 “0.to(2)”。但 “println(2)” 不能写成 “println 10“”,因为未写出方法调用的接收者 Console,所以可以写成 “Console println 10”

到这里就要讲到 apply 和 update 方法相关的约定,描述的是直接在对象(对象)后直接加圆括号的代码的情况下,那就是:

用括号传递给变量(对象)一个或多个参数时,Scala 会把它转换成对 apply 方法的调用;与此相似的,当对带有括号并包括一到若干参数的进行赋值时,编译器将使用对象的 update 方法对括号里的参数和等号右边的对象执行调用。

对上面那段话的解释可由下面几个例子得到很好的理解

1. theArray(0), 取数组的第一个元素的操作会转换成 theArray.apply(0) 操作,这也能解释为什么 Scala 数组取值不用中括号括下标的方式,因为它也是一次方法调用 阅读全文 >>

Scala 特质(trait) 的 super 方法调用是动态绑定的

在 Java 或者 Scala 的类中,super.foo() 这样的方法调用是静态绑定的,也就是说当你在代码中写下 super.foo() 的时候就能明确是调用它的父类的 foo() 方法。然而,如果是在特质中写下了 super.foo() 时,它的调用是动态绑定的。调用的实现奖在每一次特质被混入到具体类的时候才被决定。

确切的讲,特质的 super 调用与混入的次序很重要,参照下面的例子说话:

直截的讲就是超靠近后面的特质越优先起作用。当你调用带混入的类的方法是,最右侧特质的方法首先被调用。如果那个方法调用了 super,它调用其左侧特质的方法。可以这么认为,Doubling 的 super 指向了  Incrementing,Incrementing 的 super 指向了 BasicIntQueue。

来看个完整的实例实际体验一把,如果要帮助理解,最好应该实际运行一下这个实例 阅读全文 >>

Scala 的 yield 例子 (for 循环和 yield 的例子)

我看了《Programming in Scala》一书,仍然对 Scala yield 关键字的理解不甚清楚。起初我以为 Scala yield 的与 Ruby 的 yield 是一样,Ruby 中 yield 是被传入代码块的占位符。Scala 中的 yield 关键字好像总是在 for 循环中用的. 下面一些例子可以帮助你更好的理解 yield 关键字。下面是摘自 《Programming in Scala》关于 yield 的解释:

For each iteration of your for loop, yield generates a value which will be remembered. It's like the for loop has a buffer you can't see, and for each iteration of your for loop, another item is added to that buffer. When your for loop finishes running, it will return this collection of all the yielded values. The type of the collection that is returned is the same type that you were iterating over, so a Map yields a Map, a List yields a List, and so on.
Also, note that the initial collection is not changed; the for/yield construct creates a new collection according to the algorithm you specify.

上面那段话的意义就是,for 循环中的 yield 会把当前的元素记下来,保存在集合中,循环结束后将返回该集合。Scala 中 for 循环是有返回值的。如果被循环的是 Map,返回的就是  Map,被循环的是 List,返回的就是 List,以此类推。 阅读全文 >>