With the new Version 2.4/2.5 of the Play Framework they moved further towards injecting everything and removing the servers state. play.Play.application()
is now deprecated. However, I need the application in my template (e.g. to get all supported languages displayed on all pages with play.i18n.Lang.availables(play.Play.application())
).
I'm aware I could:
play.Application
explicitly to all of my templates.@()(implicit app: play.Application)
. However, in my Java-Project it's not really implicit, I have to pass it every time I render the template.play.api.Play.current
.How can I inject play.Application
in my templates?
---- Update: ----
What I've tried so far, I created the following setup:
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!
}
template.scala.html:
@(title: String)(content: Html)(implicit app: play.Application)
<html>
<head>
<title>@title</title>
</head>
<body>
<p>Is live? @app.isProd</p>
@content
</body>
</html>
Controller function:
public Result index() {
return ok(views.html.index.render("home"));
}
答案 0 :(得分:2)
您可以使用Play.current()获取应用程序,或者在控制器中注入应用程序,如此question中所述。模板应该得到类型为play.Application的参数。
它应该是这样的。
模板,假设是injectappexample.scala.html:
@(app: play.Application)
.... use the app object
控制器:
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());
}
}
值得重新考虑将应用程序对象发送到模板。如果要发送特定的配置属性值,请在控制器中注入Configuration,从配置对象中获取值并将其发送到模板。在这种情况下,根本不需要注入应用程序。
模板:
@(value: String)
.... use the value
控制器:
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"));
}
}
答案 1 :(得分:1)
我只需要研究Play框架2.6.x.可以根据文档https://www.playframework.com/documentation/2.6.x/ScalaTemplatesDependencyInjection。
将对象注入模板我实现了一个简单的示例(有点做作),我使用了scala:
test.scala.html:
@this(configuration: play.api.Configuration)
@(key: String)
config = @configuration.get[Seq[String]](key).mkString(", ")
HomeController.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(configuration: play.api.Configuration)
语句。 Play将使用注入Configuration对象的构造函数在模板后面生成一个类。
请注意,注入控制器的配置在此特定代码中没有任何作用。在我找到这个解决方案之前,我尝试了其他排列...假设你有一个由控制器调用的外部模板使用的内部模板,而内部模板需要配置对象,你需要从控制器顶部提供配置向下,并在层次结构路径中的所有模板中添加implicit configuration: play.api.Configuration
参数,直到需要它的模板,如下所示:@(message: String)(implicit messagesProvider: MessagesProvider, configuration: play.api.Configuration)
。然后,控制器注入的配置被送到顶层模板,一直到需要它的模板。
答案 2 :(得分:0)
通常不鼓励注入应用程序本身,因为这会使您的代码非常麻烦。相反,想想你实际需要什么并直接注入它。
如果你在几乎每个模板中都需要很多东西,我的建议是创建一些你可以在你的控制器中注入的上下文类,然后将它传递给模板。
答案 3 :(得分:0)
首先,虽然您在询问如何注入应用,但您真正需要的是配置。
你可以在游戏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));
}
现在,您可以在languages
中找到您的语言列表。