[英]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;
}
這個想法是讓 object 包含跨應用程序可訪問的 REST 請求級別自定義數據,顯然 scope 應該在當前請求中。 這可以用於 say.. 日志記錄 - 每當開發人員從應用程序記錄任何內容時,一些請求元數據就會隨之而來。
我不清楚 @RequestScope bean 到底是什么:
根據它的定義——我的假設是它是為每個新的 http 請求創建的,並且在該請求的生命周期內共享相同的實例。
它是什么時候由 Micronaut 構建的? 它是不可變的嗎?
在多個請求中,我可以看到相同的requestId (每個請求都需要新的 UUID)
它是@RequestScope bean 的正確用例嗎?
我遇到了一個關於@RequestScope
的問題,所以我會在這里為其他人發布一個答案。
我試圖將@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)
}
}
在這個例子中,在執行任何 controller 之前,我的過濾器( SetRequestScope
)被調用,這將設置requestScopeBean.id
但關鍵是請求 scope bean 必須包裝在javax.inject.Provider
中,否則設置字段將不起作用.
接下來,當調用GetRequestScopeBeanHere::getIdFromRequestScopeBean
時,它將可以訪問之前設置的requestScopeBean.id
這是 Micronaut 故意的: https://github.com/micronaut-projects/micronaut-core/issues/1615
它是什么時候由 Micronaut 構建的?
@RequestScope
bean 在請求處理期間創建,第一次需要 bean 時。
它是不可變的嗎?
它可能是。 當您編寫 class 時,您可以決定該 bean 是否可變。如示例中所寫, RequestContext
是可變的。 如果刪除updateRouteName
方法,則該 bean 將是不可變的。
它是@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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.