首页 > 代码库 > Scala下Play框架学习笔记(Actions,Controllers and Results)
Scala下Play框架学习笔记(Actions,Controllers and Results)
Scala下Play框架的学习是一件辛苦的事情,因为该框架比较新,scala语言也较新,所以中文资料很少,经过同事推荐,去了如下英文网站看资料:
https://www.playframework.com/documentation/2.5.x/ScalaHome
虽然我的同事以在云中飞的速度学完了,但对我来说还是任重而道远。
Action是什么?
由于Scala和Play有关的API都在play.api下面,所以其实Action的过程是这样的:
play.api.mvc.Action(play.api.mvc.Request=> play.api.mvc.Result)
例如:
def echo = Action { request =>
Ok("Got request [" + request + "]")
}
最简单的构建Action的模式如下:
Action {
Ok("Hello world")
}
有一个参数的Action可以构建如下:
Action { request =>
Ok("Got request [" + request + "]")
}
设置成隐式的request可以让其他的API在需要的时候调用:
Action { implicit request =>
Ok("Got request [" + request + "]")
}
引入特定的BodyParser参数方式如下:
Action(parse.json) { implicit request =>
Ok("Got request [" + request + "]")
}
控制器(Controllers)是Action的生成器
控制器用来产生Action类型的值,可以被定义为一个利用依赖注入特性的类或对象。依赖注入是一种用来从依赖中分离组件行为的设计模式,Play框架在scala中同时支持运行时依赖注入和编译时依赖注入。运行时依赖注入在运行时才会创建依赖关系图,并根据关系验证特定组件是否存在依赖。
依赖注入的目标:(1)同一个组件可以绑定多个接口,当用接口来实例化组件或者注入接口用于测试时很有用;(2)避免了全局静态。
Play中依赖注入的实现:通过在routes文件中的配置来创建路由,同时控制器注入构造器,创建Application的实例。另外,Play框架还提供内置的trait来允许创建在编译时与app关联的Scala接口。
当一个组件需要依赖另一个组件时,使用@Inject注解,譬如放在构造器的声明中:
import javax.inject._
import play.api.libs.ws._
class MyComponent @Inject() (ws: WSClient) {
// ...
}
注解的声明位置必须在构造器名和参数名之间。
Play框架使用依赖注入控制器的方式有两种:
(1)注入routes generator,产生控制器把他们自己作为依赖注入的路由,在build.sbt中添加如下配置:
routesGenerator := InjectedRoutesGenerator
(2)静态routes generator,如下加入到build.sbt:
routesGenerator := StaticRoutesGenerator
如果使用静态路由,每一个Action都有一个由@作为前缀修饰的已经注入的控制器:
GET /some/path @controllers.Application.index
最简单的定义action generator的方式是定义一个返回Action实例的无参方法:
package controllers
import play.api.mvc._
class Application extends Controller {
def index = Action {
Ok("It works!")
}
}
action generator 的有参数方法如下,其中参数会被Action闭包所捕获:
def hello(name: String) = Action {
Ok("Hello " + name)
}
简单HTTP请求的结果包含如下内容:
一个状态码、一个HTTP header集合、以及将被发送到web客户端的body,结果被play.api.mvc.Result所定义:
import play.api.http.HttpEntity
def index = Action {
Result(
header = ResponseHeader(200, Map.empty),
body = HttpEntity.Strict(ByteString("Hello world!"), Some("text/plain"))
)
}
用OK定义的简单结果:
def index = Action {
Ok("Hello world!")
}
这和前面获得的结果几乎相同,因为源码中OK就表示状态码为200的Status对象。
在play.api.mvc.Results接口及其伴生类可以看到许多种Result的创建方式:
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")
把浏览器重定向到新的URL也是一种简单Result的类型,不带web响应主体:
def index = Action {
Redirect("/user/home")
}
def index = Action {
Redirect("/user/home", MOVED_PERMANENTLY)
}
还没实现的Action接口:
def index(name:String) = TODO
Scala下Play框架学习笔记(Actions,Controllers and Results)