`
kidneyball
  • 浏览: 327014 次
  • 性别: Icon_minigender_1
  • 来自: 南太平洋
社区版块
存档分类
最新评论

JSF 2.0阅读笔记:视图状态 (四)

阅读更多
五. 实例验证

下面使用GlassFish v3来测试JSF2.0 RI的ViewState情况。

JSF2.0规范中提供了三个上下文参数来指定应用的ViewState策略,可在web.xml文件中使用context-param元素来配置。第一个是从JSF1.2就流传下来的javax.faces.STATE_SAVING_METHOD,取值为server或client,用于配置把视图状态数据放在服务器端还是传递到客户端,默认为server。第二个是javax.faces.PARTIAL_STATE_SAVING,取值为true或false,用于配置是否在应用范围内启用或禁用增量视图状态,默认为true。第三个是javax.faces.FULL_STATE_SAVING_VIEW_IDS,取值为一系列用逗号分隔的ViewId,用于配置当增量视图状态开启时,需要强制保存完全视图状态的页面,默认为空。

首先使用一个简单的页面测试:
<?xml version="1.0" encoding="UTF-8" ?>

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">

    <h:body>
        <h:form>
            <h:outputLabel>name</h:outputLabel>
            <h:inputText/>
            <h:commandButton value="submit"/>
        </h:form>
    </h:body>
</html>  


修改web.xml为
    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>

    <context-param>
        <param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
        <param-value>false</param-value>
    </context-param>


表示把视图状态传递到客户端,并且使用完全视图状态。访问该页面后,在浏览器中使用“查看源代码”功能来查看响应内容。可以发现其中包括这样的视图状态隐藏域:
<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="H4sIAAAAAAAAAL1WTWwbRRSerJ3/pDRJVYSgURERpJBsYjl2nKa0cdKELHF+VLuBwMEdryfxhv1jdtZZ9xDRCxy4VGo5IAXBgQOHcuLGAQQckJCKBBIXTghxBC6A+LnAm1mvf4TdVXroSDua2Zn33rz3vm/e3PkFdboUjbyc2cdlLOvY3JM3C/tEZfM3v37x3ZPOOV1CyLMRQl0ORXHVMmTHNeVdrBJHxrataypmmmXKWYYZWccm3iNUMWx9LEcJ2bCK5Pfdjz/5cPq5Twe4noNJxNtZbs2ragGdtmUSk8lXlW2NHFyxLIY69/NaMeY5r6JDJB1MCKnRdlKbLrNdhrq4DJsJhGIg0oGeaC1UYoYur0K3YlGjKpkIJFMgKaGnQyR9qxlcIHpVQTJQkBQKxkMUKCbI54gXnDwViJ8X4hMh4kuWYWCzuOgyZplVFXOey1XwJrUYddnQarP+Q4rkdjFdCsZjW9SyCWWVNVJxULUNQzIpOlEHzbLpGo2LNkMDlJhFQgnNVWxSpihatrQiqjfPBvuTYUhoa557cQJCp1sq1gmA86Q4jcs0Xc6If4d/DV07mv77ZwlFFdRTwk5JBTxmULdquSajFYaGBeynuAdTWUY1c28+g3r41AUccwsPw/Yypho2mZh69r/QGJKuZqGDoyJ0yBdGGOr3/V3TmFJkqG81t57JL6azylKwoUvHDqzBUYfqgVNMRoAywz++9/6fN95ISahDQZ1lrLvEC1wS+zZco0Do63feOtN/+4c3A1J21HSXIV7c7qkpPhJsvEwMS/Y4XppNLlqWTrB59yx97bujf34Fky8FJm0UUK8Ok45jQKqbDx5i/sGDtC5axQqkOnE8qG1RrQxOtEj5KcwgVwWXESdXwixNSZYwcHGkDoA0pbiS0Rzm3fj2zNtf4nciPK5RR7tORNyiB1Heg9CTrU8lArhq6ZDQLC4TuvPVR8/eOrq7LiEpg3pVyKSzgY0AIn0O7CkKGYZO+6DSrKksAeDo2nVc0Mm8Z9tlvj0uSJ4Agow236a818EROb21lVGWL4fuW09fWcsr9X1PtXZlW1l+IZ/ZXErnlM2N/NryjidAMwgYrQeyhhARvlXgyjq2O7u//+yL09e+iSBpBfXpFi6uYJVZVEG9rESJU4L4ePalBR8IBz3Q8y/C1V8EjY80HojDUhCTl4ufPh+8+dvzt56RUERBXaqlu4YJ+dE1E/gZtTErVdkG6ga52jbA5rsuwNpkbDY+m0qmUjPxfHJ2LqEm4zG+dh5OkWgTPg2qlHyZ7GJXZyv+z7E0VLRKznqFmH98MLFztLC/4Jet0dbmgRyT09O3xz0BzfFaCbo3eZop09uKMrwqAWXOtaMMXw+/Gf3rhk8fD9ISE9N4AwV89PA+1TC+UENVNzFVBjd4w+JFYeKS+JP+X/olP/28X4LpUODjcvtkxXabA5ioRSdyH5fPUGPURH1u9jwiPI+EeH5sRx+Dry/E0WSi2dFk/fSohX/R+7tw+Zvigbj8KHz9IS7PxJtdTjUev8O3zJqfaVCLtCKGi0ZehDq1HczqUveOWmt+DTeVJPFoeiAxkuEbCIPFtAdsb/PgEwWSv/TCCO/XcIiz4xYMjTVFfY7PDv8DUovXIu8LAAA=" autocomplete="off" />


其中视图状态信息是1636字节(1.6k)。现在把web.xml中的javax.faces.PARTIAL_STATE_SAVING上下文参数修改为true,重启应用后刷新页面。可发现视图状态隐藏域变为:
<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="H4sIAAAAAAAAAJVSQWsTQRR+3SS1DVFqDL3ZUxEEnVAwUAxigmlocKuBrWDxoJPNtDtxdnecebvZ9FDwHwiehIpXD976C8SDICjo0f/gTe/ObGLTgx4cmLezb+a9933vfe9+QElqBRdHNKUkQS7INtXBDpWlc9/ff1h98rUAThfKIqbDLvUxVj1YxkAxHcRimMnbLbCrMl4ydsXsAsLi6DEf4o1EwaVHbp5X0OiA3B+MmI/NF18evlnRV4UDkEkT4CTP4AgK5lSSZs3/jhQQG52RfeozTfw4lHHEIiQPenf+nNf7KpZM4eQum2iYrapJreDCvPRWlIRnLyVCmSIqPkiQaW1LwozJYs7E7gWENVOT6CSaIbBWMNSk3e+7va2O6VvjHy94KAXpsH2aCOxOnettKcVkN37Kol9vr+0dt0atisUyXoNaPeVs7CFF1mFhTLIAQ2EQXN9onvzMMtOJxv91oq94apKd5WxJLiHU5rx3A4ptxTyD14xqLoC2UnTico3Z82+XX32krwuw0IOi5odsOrFx0VoTdOXvqHIi20YfTHk0ZWrv08mtl8efdxxwXFj2BdX6Hg0ZQjWXR93OqO4ZWNFB04WyNjHDPAfC6vQFj+seU5wKfkgHgjUzKVNLqJrPriatrRgnwvlcfI2b+WfzVE1Fqy2EknVvnHodKbPf9nnPfQIDAAA=" autocomplete="off" />

其中视图状态信息是696字节(0.7k),减少了57%

如果把其中form中的内容重复10次
<?xml version="1.0" encoding="UTF-8" ?>

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">

    <h:body>
        <h:form>
            <h:outputLabel>name</h:outputLabel>
            <h:inputText/>
            <h:commandButton value="submit"/>
            <br/>

            <h:outputLabel>name</h:outputLabel>
            <h:inputText/>
            <h:commandButton value="submit"/>
            <br/>

            ...重复10次
        </h:form>
    </h:body>
</html> 


在完全视图状态下,视图状态尺寸是2248字节(为节省篇幅,不再贴出视图状态原文)。在增量视图状态下,视图状态尺寸是752字节,减少约66%。不难算出,在完全视图状态下,重复部分的单位视图状态尺寸是(2248-1636) / (10 - 1) = 68字节。而在增量视图状态下,重复部分的单位视图状态尺寸是 (752-696) / (10 - 1) = 6字节。随着组件数目的增多,增量视图状态的优势将更为明显。

下面测试Facelet动态页面与编程方式动态页面增量视图状态尺寸差别。

如果使用ui:repeat标签来动态创建组件,如下:

页面
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">

    <h:body>
        <h:form>
            <ui:repeat value="#{viewStateBean.range}" var="idx">
                <h:outputLabel>name#{idx}</h:outputLabel>
                <h:inputText/>
                <h:commandButton value="submit"/>
                <br/>
            </ui:repeat>
        </h:form>
    </h:body>
</html> 


Bean:
@ManagedBean(name = "viewStateBean")
@RequestScoped
public class ViewStateDemoBean {
    private List<Integer> range = new AbstractList() {
        @Override
        public Object get(int index) {
            return index;
        }

        @Override
        public int size() {
            return 10;
        }
    };

    public List<Integer> getRange() {
        return this.range;
    }
}


增量视图状态尺寸为1068字节

如果使用编程方式来动态创建组件,如下:

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets">

    <h:body>
        <h:form binding="#{viewStateBean.form}">
            <h:commandButton actionListener="#{viewStateBean.populateForm}" value="populate"/>
        </h:form>
    </h:body>
</html>  


@ManagedBean(name = "viewStateBean")
@RequestScoped
public class ViewStateDemoBean {
    private UIComponent form;

    public void setForm(UIComponent form) {
        this.form = form;
    }

    public UIComponent getForm() {
        return this.form;
    }

    public void populateForm(ActionEvent e) {
        List<UIComponent> children = form.getChildren();
        Application app = FacesContext.getCurrentInstance().getApplication();
        children.clear();
        UIComponent c;
        for (int i = 0; i < 10; i++) {
            c = app.createComponent(HtmlOutputLabel.COMPONENT_TYPE);
            c.getAttributes().put("value", String.format("name%s", i));
            children.add(c);

            c = app.createComponent(HtmlInputText.COMPONENT_TYPE);
            children.add(c);

            c = app.createComponent(HtmlCommandButton.COMPONENT_TYPE);
            c.getAttributes().put("value", "submit");
            children.add(c);

            c = app.createComponent(HtmlOutputText.COMPONENT_TYPE);
            c.getAttributes().put("value", "<br/>");
            c.getAttributes().put("escape", false);
            children.add(c);
        }
    }
}


访问页面,点populate按钮后,动态创建出10组Label + 输入框 + 按钮。增量视图状态为2124字节。可以看出,通过编程方式动态创建的组件,视图状态与完全视图状态类似。而通过Facelet的ui:repeat等特性创建的组件,则可享受到增量视图状态的优化。
2
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics