简体   繁体   English

在play框架中使用scala和java 2.1:会话使用

[英]Using scala and java in play framework 2.1 : Session usage

I'm currently using the session() of play framework in my template : 我目前正在我的模板中使用play框架的session()

@if(session().get("email")==null){
    <li><a href="@controllers.routes.General.login">Login</a></li>
}else{
    <li><a href="@controllers.routes.General.logout">Logout</a></li>
}

This template is used in all of my views. 此模板用于我的所有视图。 Some of these views are controlled by a Java controller, and some are with a Scala controller. 其中一些视图由Java控制器控制,一些视图由Scala控制器控制。

When I click on links that lead to Java controllers, I have no problems, the links for login and logout are correctly handled. 当我点击导致Java控制器的链接时,我没有问题,正确处理登录和注销的链接。

When I click on links that lead to Scala controllers, I get a [ RuntimeException: There is no HTTP Context available from here.] 当我点击导致Scala控制器的链接时,我得到一个[ RuntimeException: There is no HTTP Context available from here.]

From what I read in here about scala controllers, I understood that they didn't return the http context when rendering a page, but I really want to be able to use the session in my template. 从我在这里读到的关于scala控制器的内容来看,我理解他们在渲染页面时没有返回http上下文,但我真的希望能够在我的模板中使用会话。

I thought about using an argument session() in my view, templates and controllers, but I believe that there will be a conflict between the java session (play.mvc.http.session) and the scala session (play.api.mvc.session) when play will compile the html pages. 我想在我的视图,模板和控制器中使用参数session() ,但我相信java会话(play.mvc.http.session)和scala会话(play.api.mvc)之间会发生冲突。 session)play时会编译html页面。

Am I stuck? 我被困了? Is there a possibility to force scala controllers to give back the http context ? 是否有可能强制scala控制器回放http上下文?

The root cause maybe the Java controllers and Scala controllers are handled differently. 根本原因可能是Java控制器和Scala控制器的处理方式不同。 I have my project in Java first, and then try to add more Scala controllers. 我首先在Java中使用我的项目,然后尝试添加更多Scala控制器。 I also came across this problem (BTW, I am using Play 2.3.2). 我也遇到过这个问题(BTW,我正在使用Play 2.3.2)。

I tried to fix this by setting my own Http.Context in the TheadLocal variable using my own ActionBuilder. 我试图通过使用我自己的ActionBuilder在TheadLocal变量中设置我自己的Http.Context来解决这个问题。

import play.api.mvc._
import scala.concurrent.Future
import play.mvc.Http.Context
import play.core.j.JavaHelpers

object ContextAction extends ActionBuilder[Request] {

  def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
    Context.current.set(JavaHelpers.createJavaContext(request))
    block(request)
  }
}

Then my Scala controller actions simply use this ContextAction instead: 然后我的Scala控制器操作只是使用这个ContextAction代替:

class TestController extends Controller {
  def test = ContextAction { implicit request =>
    Ok(views.html.index())
  }
}

And this way the index template can access all request() / session() / etc. 这样索引模板就可以访问所有request()/ session()/等。

I may be wrong, but I think that your Scala controllers should look like: 我可能错了,但我认为您的Scala控制器应该如下所示:

  def myaction() = Action { implicit request =>
    ...
  }

instead of: 代替:

  def myaction() = Action {
    ...
  }

Ie, you have to add the request to the scope of your Action . 即,您必须将请求添加到您的Action范围。

And add it also to your view, at the beginning of the file: 并将其添加到您的视图,在文件的开头:

@(...)(implicit session:Session)

Okay I found a workaround this problem. 好的,我找到了解决这个问题的方法。 This is not really aesthetic, but it works, and gets rid of the problem entirely. 这不是真正的美学,但它有效,并完全摆脱了问题。

I created two different main templates : scalamain.scala.html and javamain.scala.html . 我创建了两个不同的主模板: scalamain.scala.htmljavamain.scala.html

The scalamain template is used by all views that are controlled by a Scala controller, and used the usual trick to use the session (implicit arguments, see more here ). scalamain模板由Scala控制器控制的所有视图使用,并使用通常的技巧来使用会话(隐式参数,请参见此处 )。

The javamain template is used by all view that are controlled by a Java controller. javamain模板由Java控制器控制的所有视图使用。 (these view use the session easily). (这些视图很容易使用会话)。

The two templates are of course, the same once rendered by play. 当然,这两个模板一旦通过播放呈现就相同。

I end up with some redundancy in my code and it took to separate all the actions so that view are controlled by only one type of controller(scala or java). 我最终在代码中出现了一些冗余,并将所有操作分开,以便视图仅由一种类型的控制器(scala或java)控制。

I hope this will help others with the same problem. 我希望这会帮助其他人解决同样的问题。 I validate this answer, as it solves the problem, but feel free to answer if you find a more gracious way to solve it. 我验证了这个答案,因为它解决了问题,但如果你找到一种更优雅的方法来解决它,请随时回答。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM