# 背景

测试那边转过来一个问题单,开发这边初步定位是 struts 框架接收集合参数只能接收到 256 个

# 定位

# google 一下

先直接 google 了一下,感觉回答有点偏,说是 struts2.5.15 升级到 2.5.30 就会有这个问题,是 struts 改用 ArrayList 的 TypeConverter, 我自己去代码里面看根本咩有限制


public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType) {
Collection result;
Class memberType = String.class;
    if (target != null) {
        memberType = objectTypeDeterminer.getElementClass(target.getClass(), propertyName, null);
        if (memberType == null) {
            memberType = String.class;
        }
    }
    if (toType.isAssignableFrom(value.getClass())) {
        // no need to do anything
        result = (Collection) value;
    } else if (value.getClass().isArray()) {
        Object[] objArray = (Object[]) value;
        TypeConverter converter = getTypeConverter(context);
        result = createCollection(toType, memberType, objArray.length);
        for (Object anObjArray : objArray) {
            Object convertedValue = converter.convertValue(context, target, member, propertyName, anObjArray, memberType);
            if (!TypeConverter.NO_CONVERSION_POSSIBLE.equals(convertedValue)) {
                result.add(convertedValue);
            }
        }
    } else if (Collection.class.isAssignableFrom(value.getClass())) {
        Collection col = (Collection) value;
        TypeConverter converter = getTypeConverter(context);
        result = createCollection(toType, memberType, col.size());
        for (Object aCol : col) {
            Object convertedValue = converter.convertValue(context, target, member, propertyName, aCol, memberType);
            if (!TypeConverter.NO_CONVERSION_POSSIBLE.equals(convertedValue)) {
                result.add(convertedValue);
            }
        }
    } else {
        result = createCollection(toType, memberType, -1);
        TypeConverter converter = getTypeConverter(context);
        Object convertedValue = converter.convertValue(context, target, member, propertyName, value, memberType);
        if (!TypeConverter.NO_CONVERSION_POSSIBLE.equals(convertedValue)) {
            result.add(convertedValue);
        }
    }
    return result;
}

# struts.ognl.expressionMaxLength

这时候就这专门去 clone 了一下 struts 的仓库
先切换到 2.5.33 版本,然后曲剧检索了一下 256, 还真让找到了一处配置

但是被注释掉了,翻译过来,不配置的话,就不会被限制,实际情况,本来就没有设置这个参数,应该和在这个配置没有关系,而且实际给的参数列表超过了 256, 这个参数是接收 OGNL 的个数,我们出现的问题是 OGNL 集合参数被限制在 256 以内,

# struts.ognl.autoGrowthCollectionLimit

无奈,只得继续看提交记录,好在提交记录 并不是很多,看着看着,又发现了一处


public Object getProperty(Map context, Object target, Object name) throws OgnlException {
    if (ReflectionContextState.isGettingByKeyProperty(context)
            || name.equals(XWorkCollectionPropertyAccessor.KEY_PROPERTY_FOR_CREATION)) {
        return _sAcc.getProperty(context, target, name);
    } else if (name instanceof String) {
        return super.getProperty(context, target, name);
    }
    ReflectionContextState.updateCurrentPropertyPath(context, name);
    Class lastClass = (Class) context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
    String lastProperty = (String) context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED);
    
    if (name instanceof Number
            && ReflectionContextState.isCreatingNullObjects(context)
            && objectTypeDeterminer.shouldCreateIfNew(lastClass,lastProperty,target,null,true)) {

        List list = (List) target;
        int index = ((Number) name).intValue();
        int listSize = list.size();

        if (lastClass == null || lastProperty == null) {
            return super.getProperty(context, target, name);
        }
        Class beanClass = objectTypeDeterminer.getElementClass(lastClass, lastProperty, name);
        if (listSize <= index) {
            Object result;
            if (index > autoGrowCollectionLimit) {
                throw new OgnlException("Error auto growing collection size to " + index + " which limited to "
                                        + autoGrowCollectionLimit);
            }
            for (int i = listSize; i < index; i++) {
                list.add(null);
            }
            try {
                list.add(index, result = objectFactory.buildBean(beanClass, context));
            } catch (Exception exc) {
                throw new XWorkException(exc);
            }
            return result;
        } else if (list.get(index) == null) {
            Object result;
            try {
                list.set(index, result = objectFactory.buildBean(beanClass, context));
            } catch (Exception exc) {
                throw new XWorkException(exc);
            }
            return result;
        }
    }
    return super.getProperty(context, target, name);
}

早知道就一起检索 255 了,还看了这么多提交记录,这次直接到 struts 的配置里面加上,测试了一下,果然可以

# 吐槽

struts 真的可以,增加了 default 配置,也不写到版本更新里面去,还得自己来看源码才能知道

# 推想

struts.ognl.expressionMaxLength 这个配置,看了一下他们的 issue, 还是感觉挺好笑的,2.5.21 加上后,2.5.22 又给注释掉,实际外发的版本 2.5.21 都没了,
struts.ognl.expressionMaxLength 讨论