Sky*_*ker 5 scala playframework deadbolt-2
我有一个控制器动作实现如下:
def doChangePassword = deadbolt.Restrict(List(Array(Application.USER_ROLE_KEY)))()
{ request => // <<<<<<<<<<<< here is the request
Future {
val context = JavaHelpers.createJavaContext(request)
com.feth.play.module.pa.controllers.AuthenticateBase.noCache(context.response())
val filledForm = Account.PasswordChangeForm.bindFromRequest
// compilation error here, it can't see the request ^^^^^^^
if (filledForm.hasErrors) {
// User did not select whether to link or not link
BadRequest(views.html.account.password_change(userService, filledForm))
} else {
val Some(user: UserRow) = userService.getUser(context.session)
val newPassword = filledForm.get.password
userService.changePassword(user, new MyUsernamePasswordAuthUser(newPassword), true)
Redirect(routes.Application.profile).flashing(
Application.FLASH_MESSAGE_KEY -> messagesApi.preferred(request)("playauthenticate.change_password.success")
)
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的实现导致编译错误:
[error] /home/bravegag/code/play-authenticate-usage-scala/app/controllers/Account.scala:74: Cannot find any HTTP Request here
[error] val filledForm = Account.PasswordChangeForm.bindFromRequest
[error] ^
[error] one error found
Run Code Online (Sandbox Code Playgroud)
但是,如果我改变第2行:
{ request => // <<<<<<<<<<<< here is the request
Run Code Online (Sandbox Code Playgroud)
至
{ implicit request => // <<<<<<<<<<<< here is the request
Run Code Online (Sandbox Code Playgroud)
然后它编译......但为什么呢?
您正在寻找的是隐式参数.简而言之:
隐式参数可以像常规或显式参数一样传递.如果您没有显式提供隐式参数,编译器将尝试为您传递一个.隐含可以来自各个地方.来自常见问题解答Scala在哪里寻找隐含的内容?:
- 首先看当前范围
- 当前范围中定义的隐含
- 明确的进口
- 通配符导入
- 现在看看相关的类型
- 一种类型的伴随对象
- 参数类型的隐含范围(2.9.1)
- 类型参数的隐含范围(2.8.0)
- 嵌套类型的外部对象
- 其他方面
数字1下的含义优先于数字2下的含义.
通过标记request为implicit你的榜样,你的声明"在当前范围内定义的隐".你需要有一个隐含的请求,因为bindFormRequest"请求"你传递一个.看它的签名:
bindFromRequest()(implicit request: Request[_]): Form[T]
Run Code Online (Sandbox Code Playgroud)
既然你有一个implicit request范围,编译器会自动将它传递给bindFormRequerst.
正如我在开头提到的那样,你也可以request明确地传递:
val filledForm = Account.PasswordChangeForm.bindFromRequest()(request)
Run Code Online (Sandbox Code Playgroud)
在后一种情况下,没有必要声明request,implicit因为你显然request明确地传递了.两种变体都是平等的.这取决于你喜欢哪一个.