日期:2014-05-16  浏览次数:20423 次

JSF 2.0阅读笔记:视图状态 (三)
(续 JSF 2.0阅读笔记:视图状态 (二))

在StateHelper的javadoc上明确声明:
引用
Define a Map-like contract that makes it easier for components to implement PartialStateHolder. Each UIComponent in the view will return an implementation of this interface from its UIComponent.getStateHelper() method.


可以看出,这是一个“Map-like”的通过key-value方式访问的接口,它不仅仅是组件属性的底层储存结构,还为组件的增量状态(PartialState)提供支持。组件上提供getStateHelper方法,用于返回本组件持有的StateHelper实例。我们观察任意一个API基础组件,例如UIInput,可以发现其属性(例如说,immediate属性)是这样实现的:

    public boolean isImmediate() {
        return (Boolean) getStateHelper().eval(PropertyKeys.immediate, false);
    }


    public void setImmediate(boolean immediate) {
        getStateHelper().put(PropertyKeys.immediate, immediate);
    }


作为比较,不妨回头来看看JSF1.2 API中的UIInput:
    /**
     * <p>The immediate flag.</p>
     */
    private boolean immediate = false;
    private boolean immediateSet = false;


    public boolean isImmediate() {
        if (this.immediateSet) {
            return (this.immediate);
        }
        ValueExpression ve = getValueExpression("immediate");
        if (ve != null) {
            try {
                return (Boolean.TRUE.equals(ve.getValue(getFacesContext().getELContext())));
            }
            catch (ELException e) {
                throw new FacesException(e);
            }

        } else {
            return (this.immediate);
        }
    }


    public void setImmediate(boolean immediate) {
        // if the immediate value is changing.
        if (immediate != this.immediate) {
            this.immediate = immediate;
        }
        this.immediateSet = true;
    }


可以看出使用强类型对象域(JSF1.2)与弱类型属性集合(JSF2.0)作为底层储存结构所带来的明显区别。同样,在JSF2.0中,具体组件的saveState/restoreState方法实现也变得相对简单,以UIInput为例:
    private Object[] values;

    public Object saveState(FacesContext context) {
        if (context == null) {
            throw new NullPointerException();
        }
        if (values == null) {
            values = new Object[4];
        }

        values[0] = super.saveState(context);  //将间接调用到UIComponentBase.saveState方法
        values[1] = emptyStringIsNull;
        values[2] = validateEmptyFields;
        values[3] = ((validators != null) ? validators.saveState(context) : null);
        return (values);
    }

可以看出,现在具体组件的saveState/restoreState方法中,只需要负责保存一些内部对象域的状态。而数目众多的组件属性,则无须在这里显式保存。如果具体组件中没有内部对象域需要保存,甚至可以不覆盖saveState/restoreState方法,例如UICommand组件。因为针对StateHelper的save/restore逻辑,写在了API组件的公共基类UIComponentBase(自定义组件亦可从这里开始继承)中。反观JSF1.2中的UIInput:
    public Object saveState(FacesContext context) {
        if (values == null) {
            values = new Object[14];
        }
        values[0] = super.saveState(context);
        values[1] = localValueSet ? Boolean.TRUE : Boolean.FALSE;
        values[2] = required ? Boolean.TRUE : Boolean.FALSE;
        values[3] = requiredSet ? Boolean.TRUE : Boolean.FALSE;
        values[4] = requiredMessage;
        values[5] = requiredMessageSet ? Boolean.TRUE : Boolean.FALSE;
        values[6] = converterMessage;
        values[7] = converterMessageSet ? Boolean.TRUE : Boolean.FALSE;
        values[8] = validatorMessage;
        values[9] = validatorMessageSet ? Boolean.TRUE : Boolean.FALSE;
        values[10] = this.valid ? Boolean.TRUE : Boolean.FALSE;
        values[11] = immediate ? Boolean.TRUE : Boolean.FALSE;
        values[12] = immediateSet ? Boolean.TRUE : Boolean.FALSE;
        values[13] = saveAttachedState(context, validators);
        return (values);
    }


高下立见。

4.2 增量视图状态

JSF2.0中的增量视图状态处理的核心,是由StateManagementStrateg