我在Play-scala 2.4中做了類似的事情,但是在主體關閉標簽之前有腳本進入頁腳。 我不熟悉Play的java api,但我相信這個概念仍然有用。
這是要點: https : //gist.github.com/zv3/2dad7cb63813e82f8412
控制器/ StackableAction.scala
// Borrowed from: https://github.com/rabitarochan/Play2-ChainAction/blob/master/core/src/main/scala/com/github/rabitarochan/play2/stackableaction/StackableAction.scala
abstract class StackableAction extends ActionBuilder[RequestWithAttributes] with StackableFilter {
override def filter[A](request: RequestWithAttributes[A])(f: RequestWithAttributes[A] => Future[Result]): Future[Result] = {
f(request)
}
def invokeBlock[A](req: Request[A], block: RequestWithAttributes[A] => Future[Result]): Future[Result] = {
val reqWA = new RequestWithAttributes(req, new TrieMap[AttributeKey[_], Any]())
filter(reqWA)(block)
}
}
trait StackableFilter {
def filter[A](request: RequestWithAttributes[A])(f: RequestWithAttributes[A] => Future[Result]): Future[Result]
}
trait AttributeKey[A] {
def ->(value: A): Attribute[A] = Attribute(this, value)
}
case class Attribute[A](key: AttributeKey[A], value: A) {
def toTuple: (AttributeKey[A], A) = (key, value)
}
class RequestWithAttributes[A](request: Request[A], attributes: TrieMap[AttributeKey[_], Any]) extends WrappedRequest[A](request) {
def get[B](key: AttributeKey[B]): Option[B] = attributes.get(key).asInstanceOf[Option[B]]
def set[B](key: AttributeKey[B], value: B): RequestWithAttributes[A] = {
attributes.put(key, value)
this
}
def getAll[T](implicit classTag: ClassTag[T]) = {
attributes.filterKeys {
case p: T => true
case _ => false
}
}
}
意見/支持/ JavascriptPage.scala
object JavascriptPage {
case class NonBlockingJS(key: String) extends AttributeKey[Html]
case class BlockingJS(key: String) extends AttributeKey[Html]
def addNonBlockingJS(div: String)(jscript: Html)(implicit request: Request[_]): Unit = {
request match {
case i: RequestWithAttributes[_] =>
i.set(NonBlockingJS(div), jscript)
case _ =>
}
}
// scripts that are supposed to go into the <head> tag, thus blocking scripts
def addBlockingJS(div: String)(jscript: Html)(implicit request: Request[_]): Unit = {
request match {
case i: RequestWithAttributes[_] =>
i.set(BlockingJS(div), jscript)
case _ =>
}
}
// scripts that are supposed to go before the </body> tag, non blocking scripts that is
def getNonBlockingJS()(implicit request: Request[_]): Seq[(String, Html)] = {
request match {
case i: RequestWithAttributes[_] =>
i.getAll[NonBlockingJS].toSeq.map {
case (NonBlockingJS(div), jscript: Html) => (div, jscript)
}
case _ => Seq.empty
}
}
}
inlineNonBlockingJS.scala.html
@import views.support.JavascriptPage
@(implicit request: Request[_])
<script src="/javascripts/your_javascript_app.js"></script>
<script id="non-blocking" type="text/javascript">
@defining(JavascriptPage.getNonBlockingJS()) { scripts =>
@scripts.map { case (_, item) => @item }
}
</script>
它基本上將請求(使用play的動作組合)包含在一個案例類中,該案例類具有TrieMap作為其成員之一,然后它將作為與請求關聯的額外屬性的持有者,並且這些屬性可以是javascript條目和幾乎您希望在請求期間擁有和分享的任何其他內容。