每个Play框架的web请求都是用一个新的依赖注入控制器实例的,然后静态控制器方法呢? [英] Is each Play framework web request handled with a new dependency injected controller instance, but then what about static controller methods?

查看:168
本文介绍了每个Play框架的web请求都是用一个新的依赖注入控制器实例的,然后静态控制器方法呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是关于Java的Play框架中的控制器的生命周期,如果控制器是使用静态方法的状态实例或无状态的,以及如何在控制器代码中使用依赖注入。



每个Web请求是由一个Play控制器类的新实例来处理的,即一个控制器可以在诸如注入到控制器构造函数中的服务等领域存储状态?
(文档在哪里解释?)



Play框架是否从早期版本(如果是,在什么版本?)改变了?如果控制器是有状态实例还是静态方法的无状态控制器?



在哪里可以看到有关如何使用状态控制器时将框架注入到控制器实例中的代码示例,以及如何将服务注入到静态控制器方法中?



关于后者,即注入到静态方法中,我认为这必须是框架的参数将添加,或者如果不可能,您可能会改为使用方法中的服务定位器,例如实例化一个Guice模块类,然后使用静态控制器方法中的inject.getInstance。



在下面的依赖注入控制器一节中,页面:



https:// www.playframework.com/documentation/2.4.x/JavaDependencyInjection



但是,它并没有显示代码如何实际将服务注入控制器实例(但可能与其他组件相同,即使用@Inject注释),并且当然还没有显示如何使用静态控制器方法DI。



我是对这些事情感到困惑,因为我没有找到关于我的问题的文档,我也读过一本Play(从2013年)的控制器方法应该被编程为无状态,控制器方法应该是静态的。



Howe ver,当现在使用激活器生成具有最新Play版本(2.4.6)的Java的Play应用程序时,我可以看到生成的Controller方法(Application.index)不是静态的。
此外,在以下文档页面中,控制器方法不是静态的:
https://www.playframework.com/documentation/2.4.x/JavaActions



这是令人困惑的,因为理解是非常重要的无论每个请求是否由控制器实例处理(即,如果可以使用状态),我认为这应该在关于控制器/操作的页面上比当前文档(上面链接的页面)更好地记录下来,而不是解释它



关于依赖注入的文档涉及静态和非静态方法的主题,在依赖注入控制器一节提到静态路由生成器,但我认为应该要更好地解释包括代码示例。



如果Play团队中的某个人正在阅读此问题,请在上述链接页面中添加一些信息,以供考试请提供(如果我的理解是正确的)在以前版本的Play中,控制器方法是静态的,对于那些版本,您不应该在字段中存储状态,但是在以后的版本(从x版开始),每个请求都由控制器的一个实例,因此可以使用状态(例如,构造函数参数由框架注入)



还请提供有关使用静态控制器方法注入的代码示例,并注入到状态控制器实例中,每个请求一个实例。 >

依赖注入页面中的组件生命周期部分仅提及组件,但我认为控制器生命周期及其注入也应该是明确的,因为它是如此根本和重要的知识,以便向所有开发人员清楚地沟通,以避免由于有状态而导致的误解造成的错误。

解决方案


每个Web请求是由一个Play控制器类的新实例来处理的,也就是说,控制器可以在诸如注入到控制器构造函数中的服务等领域中存储状态? (在文档中解释了?)


据我所知,控制器是默认的单例对象< /行使>。这没有明确的记录,但它暗示控制器实例被重用。请参阅 Playframework 2.4迁移指南

$ b $注入的路由生成器还支持路由上的@运算符,但是它具有稍微不同的含义(因为一切都被注入),如果您使用带前缀的控制器,而不是该控制器被直接注入,该控制器的JSR 330提供程序将被注入。例如,这可以用于消除循环依赖性问题,或者如果您希望每个请求实例化新的操作



$ b另外,请查看詹姆斯·罗珀(James Roper)发表的这一表彰(玩核心提交者)关于控制器是否为单例:


不是真的 - 如果使用Guice,每次将控制器注入某些东西,默认情况下将创建一个新的实例。也就是说,路由器是一个单例,所以通过关联,它调用的控制器是单例。但是如果你在其他地方注入一个控制器,那么它将被新建的组件实例化。


这表明默认是重用控制器响应请求时的实例,如果您想要对每个请求执行新操作,则需要使用迁移指南中描述的语法。但是,由于我更倾向于证明和尝试,而不是仅仅相信,我创建了一个简单的控制器来检查该声明:

 包控制器

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

类应用程序扩展Controller {

def index = Action {
println(this)
Ok(views.html.index(Your new application is ready。))
}

}

对此操作执行多个请求会打印相同的对象标识所有请求。但是,如果我在我的路由上使用@运算符,我开始为每个请求获取不同的标识。所以,是的,控制器是默认的(一种)单例


如果控制器是有状态的实例,或者是静态方法的无状态控制器,那么版本(如果是,在什么版本?)?


默认情况下, Play一直主张无国籍控制者,您可以在项目主页查看


Play是基于轻量级的无状态,网络友好的架构。


没有改变。因此,您不应该使用控制器的字段/属性来保留随时间/请求发生更改的数据。相反,只需使用控制器的字段/属性来继续引用其他也是无状态的组件/服务。


你可以在哪里看到代码示例关于如何在使用状态控制器时将框架注入到控制器实例中以及如何将服务注入到静态控制器方法中的示例?


关于代码示例, Activator模板库是您要去的地方。以下是在控制器级别使用依赖注入的一些示例:


  1. https://github.com/adrianhurt/play-api-rest-seed

  2. https://github.com/knoldus/playing-reactive-mongo

  3. https://github.com/KyleU/boilerplay

不支持使用静态方法的依赖注入,这就是为什么Playframework stills提供旧apis 。这里的经验法则是:选择DI和静态方法。尝试使用这两者将只会使应用程序复杂化。


My questions are about the lifecycle of controllers in the Play framework for Java, if the controllers are stateful instances or stateless with static methods, and how to use dependency injection in the controller code.

Is each web request handled by a new instance of a Play controller class, i.e. can a controller store state in fields such as services injected into the controller constructor? (where in the documentation is it explained?)

Has the Play framework changed since earlier versions (and if so, at what version?) regarding if controllers are stateful instances or stateless controllers with static methods?

Where can you see code examples about how the framework injects services into a controller instance when stateful controller is used and example of how to inject services into a static controller method?

Regarding the latter, i.e. injection into a static method I suppose that would either have to be a parameter to the method which the frameworks will add, or if not possible you maybe instead will have to use a service locator from within the method e.g. instantiate a Guice module class and then use "injector.getInstance" from within the static controller method.

This subject is touched in the section "Dependency injecting controllers" at the following page:

https://www.playframework.com/documentation/2.4.x/JavaDependencyInjection

However, it does not show with code how to actually inject services into a controller instance (but probably the same way as other "components" i.e. with @Inject annotation) and certainly it does not currently show how to use DI with a static controller method.

I am confused about these things because I have not found documentation being clear about my questions, and I have also read in a Play book (from 2013) that the controller methods should be programmed as stateless and the controller methods should be static.

However, when now using activator for generating a Play application for Java with the latest Play version (2.4.6) I can see that the generated Controller method (Application.index) is NOT static. Also, at the following documentation page, the controller method is NOT static: https://www.playframework.com/documentation/2.4.x/JavaActions

This is confusing, and since it is VERY fundamental to understand whether or not each request is handled by a Controller instance or not (i.e. if state can be used) I think this should be better documented at the page about Controller/Actions than the current documentation (the above linked page) which is not explaining it.

The documentation about dependency injection touches the subject about static and non-static methods at the section "Dependency injecting controllers" mentioning "static routes generator" but I think it should be better explained including code examples.

If someone in the Play team is reading this question, then please add some information to the above linked pages, for example please do mention (if my understanding is correct) that in previous versions of Play the controller methods were static and for those versions you should never store state in fields, but in later versions (beginning from version x?) each request is handled by an instance of a controller and can therefore use state (e.g. constructor parameters injected by the framework).

Please also provide code examples about injection used with static controller methods and injection into stateful controller instances with one instance per request.

The section "Component lifecycle" in the dependency injection page only mentions "components" but I think it should also be explicit about the controller lifecycle and its injection, since it is such a fundamental and important knowledge to communicate clearly to all developers to avoid bugs caused by misunderstandings about being stateful or not.

解决方案

Is each web request handled by a new instance of a Play controller class, i.e. can a controller store state in fields such as services injected into the controller constructor? (where in the documentation is it explained?)

As far as I can tell, controllers are by default singleton objects. This is not clearly documented, but it is implied that controller instances are reused. See the migration guide for Playframework 2.4:

The injected routes generator also supports the @ operator on routes, but it has a slightly different meaning (since everything is injected), if you prefix a controller with @, instead of that controller being directly injected, a JSR 330 Provider for that controller will be injected. This can be used, for example, to eliminate circular dependency issues, or if you want a new action instantiated per request.

Also, check this commend made by James Roper (Play core committer) about if controllers are singleton or not:

Not really - if using Guice, each time the controller is injected into something, a new instance will be created by default. That said, the router is a singleton, and so by association, the controllers it invokes are singleton. But if you inject a controller somewhere else, it will be instantiated newly for that component.

This suggests that the default is to reuse controller instances when responding to requests and, if you want a new action per request, you need to use the syntax described in the migration guide. But... since I'm more inclined to prove and try things instead of just believe, I've create a simple controller to check that statement:

package controllers

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

class Application extends Controller {

  def index = Action {
    println(this)
    Ok(views.html.index("Your new application is ready."))
  }

}

Doing multiple requests to this action prints the same object identity for all the requests made. But, if I use the @ operator on my routes, I start to get different identities for each request. So, yes, controllers are (kind of) singletons by default.

Has the Play framework changed since earlier versions (and if so, at what version?) regarding if controllers are stateful instances or stateless controllers with static methods?

By default, Play had always advocates stateless controllers, as you can see at the project homepage:

Play is based on a lightweight, stateless, web-friendly architecture.

That had not changed. So, you should not use controllers' fields/properties to keep data that changes over time/requests. Instead, just use controllers' fields/properties to keep reference to other components/services that are also stateless.

Where can you see code examples about how the framework injects services into a controller instance when stateful controller is used and example of how to inject services into a static controller method?

Regarding code examples, Activator templates repository is the place to go. Here are some examples that uses dependency injection at the controllers level:

  1. https://github.com/adrianhurt/play-api-rest-seed
  2. https://github.com/knoldus/playing-reactive-mongo
  3. https://github.com/KyleU/boilerplay

Dependency Injection with static methods is not supported and that is why Playframework stills offers old apis to use with static methods. The rule of thumb here is: choose between DI and static methods. Trying to use both will just bring complexity to your application.

这篇关于每个Play框架的web请求都是用一个新的依赖注入控制器实例的,然后静态控制器方法呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆