Java 如何在Play Framework 2.5模板中注入应用程序

Java 如何在Play Framework 2.5模板中注入应用程序,java,templates,playframework,playframework-2.0,playframework-2.5,Java,Templates,Playframework,Playframework 2.0,Playframework 2.5,在Play框架的新版本2.4/2.5中,他们进一步向注入所有内容和删除服务器状态迈进play.play.application()现在不推荐使用。但是,我需要模板中的应用程序(例如,使用play.i18n.Lang.availables(play.play.application())在所有页面上显示所有受支持的语言) 我知道我可以: 将play.Application显式传递给我的所有模板 向我的模板添加一个隐式参数,如@()(隐式应用程序:play.Application)。但是,在我的J

在Play框架的新版本2.4/2.5中,他们进一步向注入所有内容和删除服务器状态迈进
play.play.application()
现在不推荐使用。
但是,我需要模板中的应用程序(例如,使用
play.i18n.Lang.availables(play.play.application())
在所有页面上显示所有受支持的语言)

我知道我可以:

  • play.Application
    显式传递给我的所有模板
  • 向我的模板添加一个隐式参数,如
    @()(隐式应用程序:play.Application)
    。但是,在我的Java项目中,它不是真正隐式的,每次渲染模板时我都必须传递它
  • 。但是,这也需要弃用的
    play.api.play.current
如何在我的模板中注入
play.Application

----更新:----

迄今为止,我尝试了以下设置:

index.scala.html:

@(title: String)
@template(title) { //here is the play.Application obviously missing, however I don't want to pass it in every template - even worse in every Controller <-- this is the core of my question
    Welcome to my page!
}
@(title: String)(content: Html)(implicit app: play.Application)
<html>
    <head>
        <title>@title</title>
    </head>
    <body>
        <p>Is live? @app.isProd</p>
        @content
    </body>
</html>
public Result index() {
    return ok(views.html.index.render("home"));
}

您可以使用Play.current()获取应用程序,或者在控制器中注入应用程序,如下所述。模板应获取play.Application类型的参数

应该是这样的

比如说,模板是injectappexample.scala.html:

@(app: play.Application)
.... use the app object 
@this(configuration: play.api.Configuration)
@(key: String)
config = @configuration.get[Seq[String]](key).mkString(", ")
控制员:

public class SomeController extends Controller {
    Provider<Application> applicationProvider;

    @Inject 
    public SomeController(Provider<Application> applicationProvider) {
        this.applicationProvider = applicationProvider;
    }

    public Result injectAppExample() {
        return ok(injectappexample.render(applicationProvider.get());
    }
}
public class SomeController extends Controller {
    Configuration configuration;

    @Inject 
    public SomeController(Configuration configuration) {
        this.configuration = configuration;
    }

    public Result injectAppExample() {
        return ok(injectappexample.render(configuration.getString("SOME_PROPERTY"));
    }
}
控制员:

public class SomeController extends Controller {
    Provider<Application> applicationProvider;

    @Inject 
    public SomeController(Provider<Application> applicationProvider) {
        this.applicationProvider = applicationProvider;
    }

    public Result injectAppExample() {
        return ok(injectappexample.render(applicationProvider.get());
    }
}
public class SomeController extends Controller {
    Configuration configuration;

    @Inject 
    public SomeController(Configuration configuration) {
        this.configuration = configuration;
    }

    public Result injectAppExample() {
        return ok(injectappexample.render(configuration.getString("SOME_PROPERTY"));
    }
}

通常不鼓励注入应用程序本身,因为这会使您的代码非常难以测试。相反,想想你真正需要什么,然后直接注入


如果您在几乎每个模板中都需要很多东西,我的建议是创建某种上下文类,您可以将其注入控制器中,然后将其传递给模板。

首先,尽管您正在询问如何注入应用程序,但您真正需要的是配置

你可以在游戏2.5中做类似的事情。我将展示构造函数注入,您可以根据需要使用字段注入

import com.google.inject.Inject;
import play.Configuration;

public class MyClass{
    private Configuration conf;

    @Inject
    public MyClass(Configuration conf){
        this.conf = conf;
    }

}
现在您有了配置类。然后特别针对您在评论中发布的要求,您可以这样做

 List<Object> langList = conf.getList("play.i18n.langs");  
 //conf.getList("") returns an object array. 
 //You can cast to Strings (assuming you are using Java8).

 List<String> languages = new ArrayList<>(langList.size());
 for (Object object : langList) {
    languages.add(Objects.toString(object, null));
 }
List langList=conf.getList(“play.i18n.langs”);
//conf.getList(“”)返回一个对象数组。
//您可以强制转换为字符串(假设您使用的是Java8)。
列表语言=新的ArrayList(langList.size());
用于(对象:langList){
add(Objects.toString(object,null));
}

现在您可以在
语言中查看您的语言列表了

,我只需要查看一下PlayFramework2.6.x。可以根据以下文档将对象注入模板:

我实现了一个简单的示例(有点做作),并使用了scala:

test.scala.html:

@(app: play.Application)
.... use the app object 
@this(configuration: play.api.Configuration)
@(key: String)
config = @configuration.get[Seq[String]](key).mkString(", ")
家庭控制器.scala

package controllers

import javax.inject._

import play.api._
import play.api.i18n._
import play.api.mvc._

/**
 * This controller creates an `Action` to handle HTTP requests to the
 * application's home page.
 */
@Singleton
class HomeController @Inject()(cc: ControllerComponents, testView: views.html.test) (implicit configuration: Configuration) extends AbstractController(cc) with I18nSupport{

  def test() = Action  { implicit request =>
    Ok(testView("play.i18n.langs"))
  }
}
路线:

GET        /test                controllers.HomeController.test()
配置对象被注入views.html.test模板,视图本身被注入控制器。注意模板中的
@this(配置:play.api.configuration)
语句。Play将在模板后面生成一个类,该类带有注入配置对象的构造函数

请注意,注入控制器的配置在此特定代码中没有任何角色。在我找到这个解决方案之前,我尝试了其他排列。。。假设您有一个由控制器调用的外部模板使用的内部模板,并且内部模板需要配置对象,您需要从控制器自上而下地提供配置,并在层次结构路径中的所有模板中,将
隐式配置:play.api.configuration
参数添加到需要该参数的模板,如下所示:
@(消息:字符串)(隐式消息提供者:消息提供者,配置:play.api.configuration)

。然后,控制器注入的配置会一直传送到最上面的模板,直到需要它的模板。

谢谢您的回答,但是
Play.current()
在Play 2.5中也被弃用,我希望将其注入模板而不是控制器中(如何注入控制器在这里很清楚,并且有很好的文档记录)你到底需要用play.Application做什么?我想列出所有可用的语言,比如
newplay.api.i18n.DefaultLangs(play.play.Application().configuration()).availables()
,以显示语言切换器。我已经按照你的要求给出了答案。如果你对此有任何问题,一定要告诉我。:)不幸的是,没有。我仍然在寻找一种方法,将一些东西注入到我的模板中。到目前为止,所有答案都需要我将其传递给所有模板。play.Application只是一个例子,我也不知道如何注入play.Configuration之类的东西。因此,基本上您正在努力注入正确的东西??感谢您的回答,您能否进一步解释如何“直接注入”?我根本不知道如何在模板中注入任何内容,而不必每次在Java代码中呈现模板时都传递它。不,这就是我的意思——每次使用模板时,仍然需要将该上下文对象显式传递到模板中。