Jsf 会话范围bean';在每个请求中调用的后构造方法

Jsf 会话范围bean';在每个请求中调用的后构造方法,jsf,cdi,conversation-scope,Jsf,Cdi,Conversation Scope,我使用的是ConversationScope,我希望在对话开始时只调用一次PostConstruct,请参见: @Named("disciplinaDetalheMB") @ConversationScoped public class DisciplinaDetalheMBImpl { private static final long serialVersionUID = 1L; @Inject private Conversation conversat

我使用的是ConversationScope,我希望在对话开始时只调用一次PostConstruct,请参见:

@Named("disciplinaDetalheMB")
@ConversationScoped
public class DisciplinaDetalheMBImpl {

    private static final long serialVersionUID = 1L;

    @Inject
        private Conversation conversation;

    @Inject
    @AnBasicBO
    private BasicBO boPadrao;

@PostConstruct
    public void postConstruct() {
    logger.debug("Iniciando PostConstruct...");
    init();
    beginConversation();
    }

public String salvarAndRedirecionar() {
    salvar();
    if (!FacesContext.getCurrentInstance().isValidationFailed()) {
        return goToLastPage() + "?faces-redirect=true";
    } else {
        return "";
    }
    }


private void beginConversation() {
    if (!conversation.isTransient()) {
        endConversation();
    }
    conversation.begin();
    if (conversation.isTransient()) {
        throw new RuntimeException("A conversão não foi iniciada corretamente");
    }
    SessionContext.getInstance().setAttribute("cid", conversation.getId());

    }

    public BasicBO getBoPadrao() {
        return boPadrao;
    }

    public void setBoPadrao(BasicBO boPadrao) {
        this.boPadrao = boPadrao;
    }

}
因此,当我的支持bean被创建时,会话被初始化,CID被存储在会话中以供以后使用。我的XHTML中有一个commandButton“save”,当这个按钮被调用时,PostConstruct再次被调用,我不知道为什么:

<h:commandLink
            action="#{managedBeanName.salvarAndRedirecionar()}"
            styleClass="btn btn-info pull-right" value="Salvar">
            <f:ajax execute="@form" />
        </h:commandLink>

我注意到生成的HTML是:

<a id="formManterDisciplina:j_idt44:j_idt46" href="#" onclick="mojarra.ab(this,event,'action','@form',0);return false" class="btn btn-info pull-right" name="formManterDisciplina:j_idt44:j_idt46">Salvar</a>

因此,我理解“href=#”避免执行onlick。我想这就是问题所在,但我不知道如何解决。请记住:salvarAndRedirecionar()方法从未被调用,因为postConstruct总是在调用之前被调用


2) 我还有一个问题:如果我开始一段对话,但没有结束,那会有问题吗?有时我不想手动结束对话,因为我只有一个页面,我只是开始。

出现此问题的原因是,您正在调用对话范围bean的postconstruct方法中的conversation begin方法。因此,会话将在渲染响应阶段而不是之前设置为长时间运行状态。问题在于,CID参数是在HTML表单元素上呈现的,但此时会话仍然处于瞬态,因为请求之后仍然没有调用postconstruct方法。重新命名commandLink元素时会调用postconstruct方法,但为时已晚,并且HTML表单元素不会携带CID参数:

因此,解决方案包括将对话开始移动到渲染响应阶段之前的某个点。如果您使用的是JSF 2.2,则可以使用
f:viewAction
标记,如果您使用的是旧版本,则可以使用
f:event
标记

然后您将看到在HTML表单元素中呈现的CID参数,如下所示:

  • 如果使用
    f:event
    标记:
在您的页面中:

<f:metadata>
    <f:event listener="#{disciplinaDetalheMB.initConversation}" type="preRenderView" /> 
</f:metadata>
<f:metadata>
    <f:viewAction action="#{disciplinaDetalheMB.initConversation}" />
</f:metadata>
  • 如果使用
    f:viewAction
    标记:
在您的页面中:

<f:metadata>
    <f:event listener="#{disciplinaDetalheMB.initConversation}" type="preRenderView" /> 
</f:metadata>
<f:metadata>
    <f:viewAction action="#{disciplinaDetalheMB.initConversation}" />
</f:metadata>

关于第二个问题,不结束对话没有什么大问题,因为它有一个类似HTTP会话的超时。您可以根据服务器资源管理策略和空闲会话所需的生存期设置超时值。无论如何,当您只有一个页面时,最好使用视图范围的支持bean。

出现此问题的原因是您正在调用会话范围bean的postconstruct方法中的conversation begin方法。因此,会话将在渲染响应阶段而不是之前设置为长时间运行状态。问题在于,CID参数是在HTML表单元素上呈现的,但此时会话仍然处于瞬态,因为请求之后仍然没有调用postconstruct方法。重新命名commandLink元素时会调用postconstruct方法,但为时已晚,并且HTML表单元素不会携带CID参数:

因此,解决方案包括将对话开始移动到渲染响应阶段之前的某个点。如果您使用的是JSF 2.2,则可以使用
f:viewAction
标记,如果您使用的是旧版本,则可以使用
f:event
标记

然后您将看到在HTML表单元素中呈现的CID参数,如下所示:

  • 如果使用
    f:event
    标记:
在您的页面中:

<f:metadata>
    <f:event listener="#{disciplinaDetalheMB.initConversation}" type="preRenderView" /> 
</f:metadata>
<f:metadata>
    <f:viewAction action="#{disciplinaDetalheMB.initConversation}" />
</f:metadata>
  • 如果使用
    f:viewAction
    标记:
在您的页面中:

<f:metadata>
    <f:event listener="#{disciplinaDetalheMB.initConversation}" type="preRenderView" /> 
</f:metadata>
<f:metadata>
    <f:viewAction action="#{disciplinaDetalheMB.initConversation}" />
</f:metadata>

关于第二个问题,不结束对话没有什么大问题,因为它有一个类似HTTP会话的超时。您可以根据服务器资源管理策略和空闲会话所需的生存期设置超时值。无论如何,当您只有一个页面时,最好使用视图范围的支持bean。

这个类是什么范围的?为什么不向我们展示更多的类定义呢?这是第n次从[jsf]问题中删除[java]标记。您能否将此作为一个提示,在将来的[jsf]问题中不再添加[java]标记?只有当您在java应用程序类中遇到可通过
main()
method重现的问题时,才使用[java]标记。如果您有这样的问题,那么您应该重新考虑[jsf]和其他JavaEE相关标记的相关性?为什么不向我们展示更多的类定义呢?这是第n次从[jsf]问题中删除[java]标记。您能否将此作为一个提示,在将来的[jsf]问题中不再添加[java]标记?只有当您在java应用程序类中遇到可通过
main()
method重现的问题时,才使用[java]标记。如果您有这样的问题,那么您应该重新考虑[jsf]和其他与JavaEE相关的标记的相关性。但我不能将@ViewScoped(jsf注释)与@Named(CDI注释)混合使用,会出现错误。您能帮助我吗?如果您使用JSF2.2,那么就使用
javax.faces.view.ViewScoped
,而不是
javax.faces.bean.ViewScoped
。现在开始工作,再次感谢您。但是我在一些文章中读到,混合使用JSF注释和CDI注释不是一个好的实践,这是真的吗?若有,原因为何?正常工作,没有任何问题。最佳实践是在模型中只使用CDI管理的bean。这就是为什么JSF2.2使用CDI可移植扩展引入了一个新的“视图范围”范围(javax.faces.view.ViewScoped)。非常好,谢谢。但我不能将@ViewScoped(jsf注释)与@Named(CDI注释)混合使用,会出现错误。您能帮助我吗?如果您使用JSF2.2,那么就使用
javax.faces.view.ViewScoped
,而不是
javax.faces.bean.ViewScoped
。现在开始工作,再次感谢您。但是我读的太多了