SpringMVC綁定到實體數組、list、set、和map時要注意

實體的屬性前必定要用.分割,若是是使用jquery的ajax提交的一個js數組對象,則請求數據會被格式化爲java

var sub = [{name:1,num:2},{name:1,num:2}]jquery

$.post(url,{test,sub})ajax

可是springmvc綁定實體時,是檢測「.」符號,「.」以前的做爲實體list在其bean中的名稱,「.」以後的做爲實體的屬性而存在的,因此這裏要用「.」來分割屬性與list名spring

要想使用jquery自帶的方法格式化爲下面這種形式是不可能的(由於中間帶有的.符號的特殊性),因而就只能這樣提交了...本身構造一個這樣的對象數組

var sub = {"test[0].num":1,"test[0].name":56,"test[1].num":2,"test[1].name":3}mvc

$.post(url,sub)app

這樣是能夠綁定的。post

 再說說後臺的實體怎麼寫this

一、實體這樣寫:url

二、不能夠在參數中直接寫List<Test>,要在一個bean中把list做爲成員,纔可使用list綁定實體。

三、在請求參數中直接把TestBean做爲參數便可

補充1:上面2:不能夠在參數中直接寫List<Test>,要在一個bean中把list做爲成員,纔可使用list綁定實體。

(由於直接綁定到參數名的特殊性,springmvc會直接實例化參數對象類型,接口就會實例化失敗

nested exception is org.springframework.beans.BeanInstantiationException:

Could not instantiate bean class [java.util.List]: Specified class is an interface)

根本緣由是綁定到參數名與綁定到參數類型中的屬性是不一樣的邏輯,因此要把list做爲成員才行。

若是是實體的話,能夠經過反射獲取到很是多的信息,可是參數就沒那麼簡單了,因此這裏要對這兩種區別對待,簡單類型直接綁定到參數名,複雜類型要寫在實體中。

補充2:springmvc綁定實體時,是檢測「.」符號。這個檢查的代碼在:

org.springframework.beans.AbstractPropertyAccessor的方法子類實現:org.springframework.beans.BeanWrapperImpl.setPropertyValue(String propertyName, Object value)中--

public void setPropertyValue(String propertyName, Object value) throws BeansException {
        BeanWrapperImpl nestedBw;
        try {
            nestedBw = getBeanWrapperForPropertyPath(propertyName);
        }
        catch (NotReadablePropertyException ex) {
            throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
                    "Nested property in path '" + propertyName + "' does not exist", ex);
        }
        PropertyTokenHolder tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
        nestedBw.setPropertyValue(tokens, new PropertyValue(propertyName, value));
    }

nestedBw = getBeanWrapperForPropertyPath(propertyName);這一句--

protected BeanWrapperImpl getBeanWrapperForPropertyPath(String propertyPath) {
        int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath);
        // Handle nested properties recursively.
        if (pos > -1) {
            String nestedProperty = propertyPath.substring(0, pos);
            String nestedPath = propertyPath.substring(pos + 1);
            BeanWrapperImpl nestedBw = getNestedBeanWrapper(nestedProperty);
            return nestedBw.getBeanWrapperForPropertyPath(nestedPath);
        }
        else {
            return this;
        }
    }

的int pos = PropertyAccessorUtils.getFirstNestedPropertySeparatorIndex(propertyPath);獲取第一個屬性分隔符,屬性分隔符就是「.」。其中代碼是這樣的

private static int getNestedPropertySeparatorIndex(String propertyPath, boolean last) {
        boolean inKey = false;
        int length = propertyPath.length();
        int i = (last ? length - 1 : 0);
        while (last ? i >= 0 : i < length) {
            switch (propertyPath.charAt(i)) {
                case PropertyAccessor.PROPERTY_KEY_PREFIX_CHAR:  //"["
                case PropertyAccessor.PROPERTY_KEY_SUFFIX_CHAR:  //"]"
                    inKey = !inKey;
                    break;
                case PropertyAccessor.NESTED_PROPERTY_SEPARATOR_CHAR:  //"."
                    if (!inKey) {
                        return i;
                    }
            }
            if (last) {
                i--;
            }
            else {
                i++;
            }
        }
        return -1;
    }

默認的last爲false,即從開始搜索。

 因此要使springmvc能夠綁定最開始方括號那種屬性到實體中,只須要對上面那一段作處理就好了,檢測有兩對[]的話,把最後一對換爲.符號便可。具體有沒有別的影響我不肯定。

相關文章
相關標籤/搜索