【问题标题】:CDI @RequestScoped bean lifecycleCDI @RequestScoped bean 生命周期
【发布时间】:2014-10-22 20:22:42
【问题描述】:

我使用 CDI 注释定义了一个如下所示的 RequestScoped bean。我有几个使用相同 bean 的页面。当我从一个页面导航到另一个页面时。 bean obj 保持不变。即使我更改会话(使用不同的用户登录)。 bean 对象没有改变。

根据 RequestScoped 的定义,bean 实例应该为每个新请求重新创建。我错过了什么?

我正在使用 JSF/Primefaces。导航到 detail.xhtml 页面后,可以看到从 create.xhtml 页面输入的值。在 backing bean 中,不会重新分配值。

谢谢,

================================================ ==============

import javax.enterprise.context.RequestScoped;

import javax.inject.Named;

@Named("targetManager")

@RequestScoped

public class TargetManager implements Serializable { }

======================================

create.xhtml:

<ui:composition xmlns="http://www.w3.org/1999/xhtml" 
xmlns:ui="http://java.sun.com/jsf/facelets" 
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui" 
xmlns:f="http://java.sun.com/jsf/core" 
      template="../../templates/rapm.xhtml">

<ui:define name="contents">

<h:form id="createform">
  <h:outputLabel id="englishNameLabel">
     <h:outputText id="englishName" value="#{msg['view.label.englishname']}:" />
     <h:outputText id="englishNameStar" value="* " styleClass="mandatory" />
  </h:outputLabel>  
  <p:inputText id="englishTitle" value="#{targetManager.selectedTarget.englishName}" >
    <f:validator id="englishNameValidate1" validatorId="duplicateValidator" />
  </p:inputText>`

======================================

detail.xhtml:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
  xmlns:ui="http://java.sun.com/jsf/facelets"
  xmlns:h="http://java.sun.com/jsf/html"
  xmlns:p="http://primefaces.org/ui"
  xmlns:f="http://java.sun.com/jsf/core"
  template="../../templates/rapm.xhtml">

  <ui:define name="contents">

  <p:scrollPanel id="scrollPanel" styleClass="contentPanel ntb" mode="native">

     <h:outputText id="englishName" value="#{msg['.view.label.englishname']}:"/>
       <h:outputText id="englishNameValue" value="#{targetManager.selectedTarget.englishName}" />

`

【问题讨论】:

  • 怎么知道对象没有变化?
  • 我调试代码。对象 ID 始终相同。 bean的值可以从多个页面访问
  • 能否请您发布您调试代码的部分。
  • 不知道如何发布调试代码。我只是在我的审计程序中设置了一个检查点,它捕获了 bean 'targetManager' 的一些值。此时,当来自不同页面和请求的线程时,bean 的 id 始终是相同的数字。重启应用后号码id才会改变——张旭南5小时前

标签: jakarta-ee cdi


【解决方案1】:

CDI 确实为每个请求创建了一个新对象,但不是为您的 servlet 或您正在使用的对象。

假设您有一个 servlet,则该 servlet 实例仅创建一次,如果您将一个请求范围的 bean 注入此 servlet,则 CDI 无法在 servlet 内交换 bean 实例,因为这可能导致不可预测的状态。因此,CDI 为 servlet 创建了一个代理实例,该实例在 servlet 存在时始终保持不变。这就是为什么您只获得 bean 实例的单个 id,您正在检索 CDI 代理对象的 id,而不是底层 bean 的 id。当一个新的请求进来时,CDI 会创建一个新的 bean 实例,并使用这个 bean 为这个特定的请求支持代理。

【讨论】:

  • 你的解释是合理的。有一件事尚不清楚:根据代理解释,来自代理的值应该针对每个新 bean(请求)而改变。但是为什么从一个页面输入的bean的属性值(带EL)可以在另一个页面中看到而无需重新分配呢?谢谢
  • 您能发布更多关于您的设置的详细信息吗? bean,页面,......必须有其他东西有另一个范围。
  • 如果您可以与我们共享一个显示此行为的最小项目,则最好。谢谢
  • 发布 2 个简化页面。不确定设置,web.xml 和 faces-config.xml 不涉及范围。其他部分很复杂。似乎也不涉及
  • Java 的前几行是目标管理器的定义。它包含一个模型实例“selectedTarget”。该模型具有“englishName”属性。我期待不同请求的“englishName”值更改
【解决方案2】:

您可以通过输出创建时间来检查是否重新创建。您会看到它每次输出不同的时间,这意味着它会在每次请求时重新创建。

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
@Named("targetInstructionManager")
@RequestScoped
public class TargetInstructionManager implements Serializable { 
    public TargetInstructionManager (){
            System.out.println(System.currentTimeMillis());
        }
}

【讨论】:

  • 我有一个@PostConstruct public void init(){},我也把你的构造函数放在了类中。两者仅在部署时调用。应用启动时和启动后,不再调用它
猜你喜欢
  • 1970-01-01
  • 2014-06-02
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 2019-08-04
  • 2013-11-22
  • 2015-07-14
  • 1970-01-01
相关资源
最近更新 更多