Play 2.0 中文资料 - 组合 Action
本章介绍几种定义通用 Action 功能的方法.
基本的 Action 组合
我们首先从一个简单的日志装饰器(logging decorator) 开始: 我们想要记录下当前 Action 每次被调用的日志.
我们不直接就定义自己的 Action, 而是首先提供一个用于创建标准 Action 的帮助方法:
接着你可以这么来使用:
Unmi 注: LoggingAction 接受的参数是个 Request[AnyContent] => Result 函数,而 request => Ok("Hello World") 就是这个类型,方法只有一个参数时,圆括号可写成花括号。实际的执行效果与下面代码一样:
前面的例子很简单,且只是用了默认的
然后:
Unmi 注: 这与前面的例子其实差不多,不同之处就是多加了一个参数 bp: BodyParser[A],它需要用到泛型 A,两个参数时是柯里化了的。
包装已有的 Action
另一种定义自己的
现在你可以用它去包装任何其他的 Action 值:
Unmi 注: 这里隐含的东西比较多,Logging 前有 case,它是一个样本类, case 在这里会为我们自动做几件事情:
1. Logging 后面的参数 action: Action[A] 会自动用 val 声明为一个实例变量,在 apply 方法中就用到了
2. 会生成一个工厂方法,也就是说可以用 Logging(action) 来构造 Logging 对象, 实际是会自动创建一个 Loggin 伴生对象,其中声明 apply(action: Action[A]): Logging 工厂方法。
3. 其他会生成 toSring, hashCode, equals 等方法就不重要
还有 Logging 继承自 Action,所以后面可以直接用 Logging 对象作为 Action。所以执行过程是:
1. Action { Ok("Hello World") } 作为参数用于构造 Logging 实例
2. 由于 Logging 本身是一个 Action,所以它的 apply(request: Request[A]) 方法会被调用执行
3. action(request) 又会调用第一步构造的 Action 实例的 apply(request:Request[A]) 方法
注: 它也将重用到被包装 Action 的 Body 解析器, 这时你就要这么写:
另一种不需要定义永久链接 https://yanbin.blog/play2-0-tutorials-cn-actions-composition/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
基本的 Action 组合
我们首先从一个简单的日志装饰器(logging decorator) 开始: 我们想要记录下当前 Action 每次被调用的日志.
我们不直接就定义自己的 Action, 而是首先提供一个用于创建标准 Action 的帮助方法:
1def LoggingAction(f: Request[AnyContent] => Result): Action[AnyContent] = {
2 Action { request =>
3 Logger.info("Calling action")
4 f(request)
5 }
6}接着你可以这么来使用:
1def index = LoggingAction { request =>
2 Ok("Hello World")
3}Unmi 注: LoggingAction 接受的参数是个 Request[AnyContent] => Result 函数,而 request => Ok("Hello World") 就是这个类型,方法只有一个参数时,圆括号可写成花括号。实际的执行效果与下面代码一样:
1def index = Action { request =>
2 Logger.info("Calling action")
3 Ok("Hello World")
4}前面的例子很简单,且只是用了默认的
parse.anyContent Body 解析器,因为这种方式我们无从指定自己的 Body 解析器。当然我们还可以再定义一个帮助方法:1def LoggingAction[A](bp: BodyParser[A])(f: Request[A] => Result): Action[A] = {
2 Action(bp) { request =>
3 Logger.info("Calling action")
4 f(request)
5 }
6}然后:
1def index = LoggingAction(parse.text) { request =>
2 Ok("Hello World")
3}Unmi 注: 这与前面的例子其实差不多,不同之处就是多加了一个参数 bp: BodyParser[A],它需要用到泛型 A,两个参数时是柯里化了的。
包装已有的 Action
另一种定义自己的
LoggingAction 的方式是包装另一个 Action:1case class Logging[A](action: Action[A]) extends Action[A] {
2
3 def apply(request: Request[A]): Result = {
4 Logger.info("Calling action")
5 action(request)
6 }
7
8 lazy val parser = action.parser
9}现在你可以用它去包装任何其他的 Action 值:
1def index = Logging {
2 Action {
3 Ok("Hello World")
4 }
5}Unmi 注: 这里隐含的东西比较多,Logging 前有 case,它是一个样本类, case 在这里会为我们自动做几件事情:
1. Logging 后面的参数 action: Action[A] 会自动用 val 声明为一个实例变量,在 apply 方法中就用到了
2. 会生成一个工厂方法,也就是说可以用 Logging(action) 来构造 Logging 对象, 实际是会自动创建一个 Loggin 伴生对象,其中声明 apply(action: Action[A]): Logging 工厂方法。
3. 其他会生成 toSring, hashCode, equals 等方法就不重要
还有 Logging 继承自 Action,所以后面可以直接用 Logging 对象作为 Action。所以执行过程是:
1. Action { Ok("Hello World") } 作为参数用于构造 Logging 实例
2. 由于 Logging 本身是一个 Action,所以它的 apply(request: Request[A]) 方法会被调用执行
3. action(request) 又会调用第一步构造的 Action 实例的 apply(request:Request[A]) 方法
注: 它也将重用到被包装 Action 的 Body 解析器, 这时你就要这么写:
1def index = Logging {
2 Action(parse.text) {
3 Ok("Hello World")
4 }
5}另一种不需要定义
Logging 类,但能达到同样效果的方式是:1def Logging[A](action: Action[A]): Action[A] = {
2 Action(action.parser) { request =>
3 Logger.info("Calling action")
4 action(request)
5 }
6}[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。