【问题标题】:How to prevent a request scoped bean method being called multiple times in a JSF application?如何防止在 JSF 应用程序中多次调用请求范围的 bean 方法?
【发布时间】:2011-04-25 06:08:07
【问题描述】:

好的,有了this question 的所有答案,我仍然无法处理我的问题。 我有以下星座:

在 JSF (1.1) webapp 中,我有一个请求范围的 bean beanof class Bean。当用户快速单击commandButton 多次以将他重定向到insult.xhtml 页面时,doSomethingThatTakesALittleLongerAndShouldOnlyBeDoneOnce 方法可能会被多次调用(在 Tomcat 6 上)。我怎样才能防止这种情况发生?

...
public Bean() {
    HttpSession session = ((HttpSession) FacesContext.getCurrentInstance()
             .getExternalContext().getSession(false));
    if(session != null && session.getAttribute("done") != null) {
        doSomethingThatTakesALittleLongerAndShouldOnlyBeDoneOnce();
        session.setAttribute("done", "done");
    }
}

public void doSomethingThatTakesALittleLongerAndShouldOnlyBeDoneOnce() {
    this.bossInsult = generateBossInsult();
}

侮辱.xhtml:

<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core">
<html>
    <body>
    #{bean.bossInsult}
    </body>
</html>
</ui:composition>

【问题讨论】:

    标签: jsf httpsession thread-safety


    【解决方案1】:

    使 bean 会话具有作用域并使用 @PostConstruct 注释方法。如果您坚持将其保留在请求范围内,则将该部分拆分为会话范围 bean,并使用 @ManagedProperty 使其成为请求范围 bean 的托管属性。

    @ManagedBean
    @RequestScoped
    public class Bean {
        @ManagedProperty(value="#{insultBean}")
        private InsultBean insultBean;
    }
    

    @ManagedBean
    @SessionScoped
    public class InsultBean {
        @PostConstruct
        public void init() {
            this.bossInsult = generateBossInsult();
        }
    }
    

    然后 JSF 会注意它在会话期间只被创建和调用一次。


    更新:抱歉,您使用的是 JSF 1.x。如果是 1.2,则以下实现相同:

    public class Bean {
        private InsultBean insultBean;
    }
    

    public class InsultBean {
        @PostConstruct
        public void init() {
            this.bossInsult = generateBossInsult();
        }
    }
    

    <managed-bean>
        <managed-bean-name>insultBean</managed-bean-name>
        <managed-bean-class>com.example.InsultBean</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
    </managed-bean>
    
    <managed-bean>
        <managed-bean-name>bean</managed-bean-name>
        <managed-bean-class>com.example.Bean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>insultBean</property-name>
            <value>#{insultBean}</value>
        </managed-property>
    </managed-bean>
    

    【讨论】:

    • 哇。请原谅我的例子不够精确。我绑定到 JSF 1。我已经尝试将 bean 放在会话范围内,但结果相同:(
    • 谢谢。所以我注定要使用 JSF 1.1?
    【解决方案2】:

    一旦点击按钮,就用 javascript 禁用该按钮。

    【讨论】:

    • 这行得通,不幸的是,实际情况与我的示例略有不同。重定向来自我无法控制的第三方页面。
    猜你喜欢
    • 1970-01-01
    • 2011-11-11
    • 2011-08-15
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 2011-09-02
    • 2014-12-02
    • 1970-01-01
    相关资源
    最近更新 更多