【问题标题】:ViewScoped works like RequestScoped - why?ViewScoped 像 RequestScoped 一样工作 - 为什么?
【发布时间】:2011-07-10 09:01:24
【问题描述】:

我写了一个 ViewScoped Managed-Bean,每次在我的浏览器中刷新页面时,Managed-Bean 似乎被重新创建,文章为空,它加载了一个新的文章对象等等。对我来说,它看起来与 RequestScoped 的行为相同。

我使用 Eclipse IDE for Java EE Developers、最新的 JDK、Apache Tomcat 7.0.8 和 Mojarra 2.0.3。

怎么了?

托管豆:

...
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
...
@ManagedBean
@ViewScoped
public class CreateArticle {

    @ManagedProperty(value = "#{index.facade}")
    private PersistenceFacade facade;
    private Article article;
    private Vector<ArtCategory> artcat;

    public CreateArticle() {
        artcat = ArtCategory.listArtCat();
    }

    @PostConstruct
    public void postCreateArticle() {
        if (article == null) {
            try {
                article = facade.createArticle();
            } catch (DAOException e) {
                e.printStackTrace();
            }
        }
    }

    public void setFacade(PersistenceFacade facade) {
        this.facade = facade;
    }

    public Vector<ArtCategory> getArtcat() {
        return artcat;
    }

    public Article getArticle() {
        return article;
    }

    public String save() {
        try {
            facade.save(article);
            facade.commit();
        } catch (DAOException e) {
            e.printStackTrace();
        }
        FacesMessage message = new FacesMessage(
                "Successful!");
        FacesContext.getCurrentInstance().addMessage(null, message);
        return "/testpage.xhtml";
    }

}

createArticle.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html">
<h:head>
    <title>Create article</title>
</h:head>
<h:body>
    <h1>
        <h:outputText value="System" />
    </h1>
    <h2>
        <h:outputText value="Test1" />
    </h2>
    <h3>
        <h:outputText value="Test2" />
    </h3>
    <h:form>
        <h:panelGrid columns="3">
            <h:outputLabel for="artname">Articlename</h:outputLabel>
            <h:inputText id="artname" value="#{createArticle.article.artname}"
                required="true">
                <f:ajax event="blur" render="artnameMessage" />
            </h:inputText>
            <h:message id="artnameMessage" for="artname" />

            <h:outputLabel for="briefdesc">Brief description</h:outputLabel>
            <h:inputTextarea id="briefdesc"
                value="#{createArticle.article.briefdesc}" required="false">
                <f:ajax event="blur" render="briefdescMessage" />
            </h:inputTextarea>
            <h:message id="briefdescMessage" for="briefdesc" />

            <h:outputLabel for="price">Price</h:outputLabel>
            <h:inputText id="price" value="#{createArticle.article.price}"
                required="true">
                <f:ajax event="blur" render="priceMessage" />
            </h:inputText>
            <h:message id="priceMessage" for="price" />

            <h:outputLabel for="selectartcat">Article Category</h:outputLabel>
            <h:selectOneMenu id="selectartcat"
                value="#{createArticle.article.artcatnr}" required="true">
                <f:selectItems value="#{createArticle.artcat}" var="artcat"
                    itemLabel="#{artcat.name}" itemValue="#{artcat.artcatnr}" />
                <f:ajax event="blur" render="selectartcatMessage" />
            </h:selectOneMenu>
            <h:message id="selectartcatMessage" for="selectartcat" />

            <h:panelGroup />
            <h:commandButton value="Save"
                action="#{createArticle.save}">
                <f:ajax execute="@form" render="@form" />
            </h:commandButton>
            <h:messages globalOnly="true" layout="table" />
        </h:panelGrid>
    </h:form>
</h:body>
</html>

【问题讨论】:

    标签: java jsf jsf-2 facelets


    【解决方案1】:

    还要确保在 ViewScoped bean 上实现 Serializable,就像使用 SessionScoped bean 一样。

    【讨论】:

    • 是的,不要忘记将 private static final long serialVersionUID = xxxx; 设置为 project-wide-unique 并将所有自定义 JAR 序列号包含到 bean 中。
    【解决方案2】:

    这是预期的行为。当您通过在浏览器中刷新页面来触发全新的 HTTP GET 请求时,它肯定会被重新创建。否则它会像一个会话范围的 bean 一样,它会使视图范围无用(想想不同浏览器选项卡中的新 GET 请求!)。但是,当您调用任何 ajax 请求或在同一视图中提交表单时,它不会重新创建。每次都会重新创建一个请求范围的请求。这是视图范围 bean 的核心点/优势。

    【讨论】:

    • ...我一直认为 view 被定义为同一个 page!我的意思是 xyz.xhtml (xyz.jsf) 是 JSF 术语中的视图(viewParams,查看任何内容,...)。混乱到骨子里。每天阅读您的帖子变得更好。
    • @Kawu:是的,有些术语充满了歧义。如何解释它们取决于观点;)更简单地说:只要您向其提交 POST 请求,视图范围的 bean 就会存在。当您向其发送 GET 请求时,将创建一个新的视图范围。
    • 如果你刷新,你就不再在同一个页面上了!服务器绝对无法判断您是否刷新了当前选项卡或打开了新页面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-24
    • 1970-01-01
    • 2020-03-27
    • 2019-06-10
    • 2015-10-12
    • 2012-05-12
    • 2011-05-13
    相关资源
    最近更新 更多