CDI ConversationScoped长期运行的Bean无法运行

nog*_*awa 2 jsf cdi java-ee-6 jboss-weld

我在理解Weld或CDI的会话范围时遇到了一些问题.

在我的JSF Faclets页面中,我调用:

        <f:metadata>
            <f:event type="preRenderView" listener="#{viewBean.start}" />
        </f:metadata>
Run Code Online (Sandbox Code Playgroud)

豆子:

import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
@Named
@ConversationScoped
public class ViewBean implements Serializable {

@Inject
    private Conversation conversation;

public void start() {
    if (conversation.isTransient()) {
        System.out.println("START CONVERSATION");
        conversation.begin();

    }
}
Run Code Online (Sandbox Code Playgroud)

现在每次刷新浏览器时,都会启动一个新的对话.这是正确的行为吗?那么为什么谈话总是短暂的?没有异常被抛出.beans.xml已创建并为空:

<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
Run Code Online (Sandbox Code Playgroud)

jan*_*oth 5

简短回答:是的,这是正确的行为.

答案很长:对话代表一个"工作单元",必须明确区分.这是通过显式调用conversation.begin()完成的 - 就像你已经做的那样.如果你想在多个请求上使用相同的对话,你必须传播它 - 这是你没有做的:-)

传播对话时,会话ID会附加到请求中.这告诉容器需要哪个对话.当您在请求中点击没有会话ID的刷新按钮时,会为每个请求生成一个新会话.

从文档:

会话上下文自动传播任何JSF面部请求(JSF表单提交)或重定向.它不会自动传播非面部请求,例如,通过链接导航.

如果您需要手动传播它,只需将conversation-id添加到请求中:

<h:link outcome="/addProduct.xhtml" value="Add Product">
   <f:param name="cid" value="#{javax.enterprise.context.conversation.id}"/>
</h:link>
Run Code Online (Sandbox Code Playgroud)

这里解释所有这些以及更多内容.