micronaut @RequestScope - 不为每个传入的 http 请求创建 bean
micronaut @RequestScope - not creating bean per incoming http-request
我有一个 class 以下 class 作为 RequestScope bean:
@RequestScope
class RequestContext {
private String requestId;
private String traceId;
private String authorisedId;
private String routeName;
// few more fields
@Inject RequestContext(SecurityContext securityContext) {
this.requestId = UUID.randomUUID().toString();
if(securityService.getAuthentication().isPresent()){
this.authorisedId = (securityService
.getAuthentication().get()).getUserId().toString();
}
}
/* to be updated in controller method interceptors */
public void updateRouteName(String name){
this.routeName = name;
}
我们的想法是让一个对象包含跨应用程序可访问的 REST 请求级别自定义数据,其范围显然应该在当前请求内。这可以用于 say.. 日志记录 - 每当开发人员从应用程序记录任何内容时,一些请求元数据就会随之而来。
我不清楚@RequestScope bean 到底是什么:
根据它的定义 - 我的假设是它是为每个新的 http 请求创建的,并且在该请求的生命周期内共享相同的实例。
Micronaut 什么时候建造的?它是不可变的吗?
在多个请求中,我可以看到相同的 requestId(每个请求都需要新的 UUID)
它是@RequestScope bean 的正确用例吗?
when is it constructed by Micronaut ?
一个 @RequestScope
bean 在请求处理期间创建,第一次需要 bean。
Is it immutable ?
有可能。当您编写 class 时,您可以决定该 bean 是否可变。正如您的示例中所写, RequestContext
是可变的。如果删除 updateRouteName
方法,则该 bean 将是不可变的。
Is it the right use-case for @RequestScope bean?
我不这么认为,但这确实是一个基于意见的问题。
编辑:基于下面添加的评论
在 https://github.com/jeffbrown/rscope 查看项目。
package rscope;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
@Controller("/")
public class DemoController {
private final DemoBean demoBean;
public DemoController(DemoBean demoBean) {
this.demoBean = demoBean;
}
@Get("/doit")
public String doit() {
return String.format("Bean identity: %d", demoBean.getBeanIdentity());
}
}
package rscope;
import io.micronaut.runtime.http.scope.RequestScope;
@RequestScope
public class DemoBean {
public DemoBean() {
}
public int getBeanIdentity() {
return System.identityHashCode(this);
}
}
package rscope;
import io.micronaut.http.client.RxHttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@MicronautTest
public class DemoControllerTest {
@Inject
@Client("/")
RxHttpClient client;
@Test
public void testIndex() throws Exception {
// these will contain the identity of the the DemoBean used to handle these requests
String firstResponse = client.toBlocking().retrieve("/doit");
String secondResponse = client.toBlocking().retrieve("/doit");
assertTrue(firstResponse.matches("^Bean identity: \d*$"));
assertTrue(secondResponse.matches("^Bean identity: \d*$"));
// if you modify DemoBean to be @Singleton instead of
// @RequestScope, this will fail because the same instance
// will be used for both requests
assertNotEquals(firstResponse, secondResponse);
}
}
我 运行 遇到了一个关于 @RequestScope
的问题,所以我会 post 在这里为其他人提供答案。
我试图将一个 @RequestScope
bean 注入到 HTTP 过滤器中,在 bean 中设置一个值,然后稍后从另一个 bean 中读取它。例如
@RequestScope
class RequestScopeBean() {
var id: Int? = null
}
@Filter
class SetRequestScopeBeanHere(
private val requestScopeBean: Provider<RequestScopeBean>
) {
override fun doFilterOnce(request: HttpRequest<*>, chain: ServerFilterChain): Publisher<MutableHttpResponse<*>> {
requestScopeBean.get().id = // id from Http Request
}
}
@Singleton
class GetRequestScopeBeanHere(
private val requestScopeBean: Provider<RequestScopeBean>
) {
fun getIdFromRequestScopeBean() {
println(requestScopeBean.get().id)
}
}
在此示例中,在执行任何控制器之前调用我的过滤器 (SetRequestScope
),这将设置 requestScopeBean.id
但关键是请求范围 bean 必须包装在 javax.inject.Provider
, 否则设置字段将不起作用。
接下来,当调用 GetRequestScopeBeanHere::getIdFromRequestScopeBean
时,它将可以访问之前设置的 requestScopeBean.id
这是 Micronaut 故意的:
https://github.com/micronaut-projects/micronaut-core/issues/1615
我有一个 class 以下 class 作为 RequestScope bean:
@RequestScope
class RequestContext {
private String requestId;
private String traceId;
private String authorisedId;
private String routeName;
// few more fields
@Inject RequestContext(SecurityContext securityContext) {
this.requestId = UUID.randomUUID().toString();
if(securityService.getAuthentication().isPresent()){
this.authorisedId = (securityService
.getAuthentication().get()).getUserId().toString();
}
}
/* to be updated in controller method interceptors */
public void updateRouteName(String name){
this.routeName = name;
}
我们的想法是让一个对象包含跨应用程序可访问的 REST 请求级别自定义数据,其范围显然应该在当前请求内。这可以用于 say.. 日志记录 - 每当开发人员从应用程序记录任何内容时,一些请求元数据就会随之而来。
我不清楚@RequestScope bean 到底是什么:
根据它的定义 - 我的假设是它是为每个新的 http 请求创建的,并且在该请求的生命周期内共享相同的实例。
Micronaut 什么时候建造的?它是不可变的吗?
在多个请求中,我可以看到相同的 requestId(每个请求都需要新的 UUID)
它是@RequestScope bean 的正确用例吗?
when is it constructed by Micronaut ?
一个 @RequestScope
bean 在请求处理期间创建,第一次需要 bean。
Is it immutable ?
有可能。当您编写 class 时,您可以决定该 bean 是否可变。正如您的示例中所写, RequestContext
是可变的。如果删除 updateRouteName
方法,则该 bean 将是不可变的。
Is it the right use-case for @RequestScope bean?
我不这么认为,但这确实是一个基于意见的问题。
编辑:基于下面添加的评论
在 https://github.com/jeffbrown/rscope 查看项目。
package rscope;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
@Controller("/")
public class DemoController {
private final DemoBean demoBean;
public DemoController(DemoBean demoBean) {
this.demoBean = demoBean;
}
@Get("/doit")
public String doit() {
return String.format("Bean identity: %d", demoBean.getBeanIdentity());
}
}
package rscope;
import io.micronaut.runtime.http.scope.RequestScope;
@RequestScope
public class DemoBean {
public DemoBean() {
}
public int getBeanIdentity() {
return System.identityHashCode(this);
}
}
package rscope;
import io.micronaut.http.client.RxHttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
@MicronautTest
public class DemoControllerTest {
@Inject
@Client("/")
RxHttpClient client;
@Test
public void testIndex() throws Exception {
// these will contain the identity of the the DemoBean used to handle these requests
String firstResponse = client.toBlocking().retrieve("/doit");
String secondResponse = client.toBlocking().retrieve("/doit");
assertTrue(firstResponse.matches("^Bean identity: \d*$"));
assertTrue(secondResponse.matches("^Bean identity: \d*$"));
// if you modify DemoBean to be @Singleton instead of
// @RequestScope, this will fail because the same instance
// will be used for both requests
assertNotEquals(firstResponse, secondResponse);
}
}
我 运行 遇到了一个关于 @RequestScope
的问题,所以我会 post 在这里为其他人提供答案。
我试图将一个 @RequestScope
bean 注入到 HTTP 过滤器中,在 bean 中设置一个值,然后稍后从另一个 bean 中读取它。例如
@RequestScope
class RequestScopeBean() {
var id: Int? = null
}
@Filter
class SetRequestScopeBeanHere(
private val requestScopeBean: Provider<RequestScopeBean>
) {
override fun doFilterOnce(request: HttpRequest<*>, chain: ServerFilterChain): Publisher<MutableHttpResponse<*>> {
requestScopeBean.get().id = // id from Http Request
}
}
@Singleton
class GetRequestScopeBeanHere(
private val requestScopeBean: Provider<RequestScopeBean>
) {
fun getIdFromRequestScopeBean() {
println(requestScopeBean.get().id)
}
}
在此示例中,在执行任何控制器之前调用我的过滤器 (SetRequestScope
),这将设置 requestScopeBean.id
但关键是请求范围 bean 必须包装在 javax.inject.Provider
, 否则设置字段将不起作用。
接下来,当调用 GetRequestScopeBeanHere::getIdFromRequestScopeBean
时,它将可以访问之前设置的 requestScopeBean.id
这是 Micronaut 故意的: https://github.com/micronaut-projects/micronaut-core/issues/1615