问题记录: Spring框架中使用List接收前端数组参数后台抛出索引越界

实际情景:
数据库中有一张表,该表的字段足足有270多个!!!而这张表对应的恰好是一个银行的一个理财对象(这里就牵扯到银行的理财业务了)我们可以简单的理解为这张表就对应着银行的一项理财业务(银行的理财业务还有很多,这只是其中一个比较特殊的),而我们的系统有一个功能就是要配置这一项理财业务;
顾名思义要配置就要获取这张表的所有字段,然后对这些字段进行一些设置,以便后期在页面上录入数据的时候只需要按照我们配置的要求录入即可;

1 提交参数

前端提交的参数是一个json格式如下:(情况一样)
columsList 在后台controller的方法中是一个pojo的属性:

//第一种
{
  "tableName": "XXX_TABLE",
  "ownerName": "XXX",
  "...": "...",
  "columnsList": [
    "xxx1",
    "xxx2",
    "xxx3",
    "xxx4",
    "xxx5",
    "xxx6",
    "..."
  ]
}
//第二种
{
  "tableName": "XXX_TABLE",
  "ownerName": "XXX",
  "columnsList[0]": "xxx0",
  "columnsList[1]": "xxx0",
  "columnsList[2]": "xxx0",
  "columnsList[3]": "xxx0",
  "columnsList[4]": "xxx0",
  "columnsList[m]": "xxxm",
  "columnsList[...]": "xxx..."
}

2 后台controller接收参数格式

使用的pojo实体进行的接受,格式如下

class DemoPojo{
private String tableName;
priate String ownerName;
private List<ColumnInfo> columnsList;
...
}

3 抛出异常信息

异常信息如下:

org.springframework.beans.InvalidPropertyException: Invalid property 'columnsList[256]' of bean class [com.suning.asvp.mer.entity.InviteCooperationInfo]: Index of out of bounds in property path 'columnsList[256]'; nested exception is java.lang.IndexOutOfBoundsException: Index: 256, Size: 256

4 抛出异常原因

查看Spring源码中可以看到如下代码:

public class DataBinder implements PropertyEditorRegistry, TypeConverter {
    public static final String DEFAULT_OBJECT_NAME = "target";
    public static final int DEFAULT_AUTO_GROW_COLLECTION_LIMIT = 256;
    protected static final Log logger = LogFactory.getLog(DataBinder.class);
    public DataBinder(@Nullable Object target, String objectName) {
        this.directFieldAccess = false;
        this.ignoreUnknownFields = true;
        this.ignoreInvalidFields = false;
        this.autoGrowNestedPaths = true;
        this.autoGrowCollectionLimit = 256;
        this.bindingErrorProcessor = new DefaultBindingErrorProcessor();
        this.validators = new ArrayList();
        this.target = ObjectUtils.unwrapOptional(target);
        this.objectName = objectName;
    }
    //...
    public void setAutoGrowCollectionLimit(int autoGrowCollectionLimit) {
        Assert.state(this.bindingResult == null, "DataBinder is already initialized - call setAutoGrowCollectionLimit before other configuration methods");
        this.autoGrowCollectionLimit = autoGrowCollectionLimit;
    }
}

上面代码可以看出默认在Spring中我们的集合中可以增长的个数只能0-255也就是256个,多了就会抛出索引越界的异常,
由此可见我们异常产生的原因就是这里的问题

5 解决

网上解决思路很多,但是这里我是使用的是最简单的一种方式
Controller 中添加如下方法:

@RestController
@RequestMapping("/demo")
class DemoController{
//.....此处省去其他业务代码

//添加方法覆盖Spring默认的集合自增长最大长度(性能优化)
  @InitBinder  
  public void initListBinder(WebDataBinder binder)  
  {  
      // 设置需要包裹的元素个数,默认为256  
      binder.setAutoGrowCollectionLimit(1024);  
  } 
}

6 小结

注意只有在使用Spring或者SpringBoot框架的时候才会遇到此问题,其实解决思路不只有这一种比如:
1 将这些数组的参数在前端拼接成字符串传到后台,然后截取;
2 将整个json前端转换成json字符串,后台使用一个String类型变量接受,之后转换成pojo或者Map

<think>好的,用户的问题是如何在Java中将List数据进行分片并批处理,每组30条,需要示例代码。首先,我需要回忆一下Java中处理集合分片的常见方法。 首先想到的是使用subList方法,通过循环来分割列表。例如,总共有n个元素,每30个一组,那么循环的次数就是总元素数除以30,向上取整。在每次循环中,使用subList(start, end)来获取子列表。需要注意的是,subList的结束索引不能超过列表的大小,否则会抛出异常,所以在最后一次循环时,end应该取列表的size()和当前计算值的较小值。 然后,用户可能还需要示例代码。应该提供一个简单明了的示例,比如一个工具方法,接收原始列表和分片大小,返回一个包含各个分片的列表。代码中需要处理边界情况,比如空列表或者分片大小大于列表长度的情况。 接下来,考虑用户提到的批处理,可能需要结合Spring Batch或者其他批处理框架。但用户的问题可能更偏向于基础的分片处理,所以先给出核心的分片方法,再提到如何与批处理框架结合。例如,可以提到使用Spring Batch的ItemReader实现分页读取,或者使用BulkRequest进行批量操作。 另外,参考用户提供的引用,引用[3]提到了BulkRequest类,引用[2]提到了Spring Batch的ItemReader,这些可以作为扩展内容。需要确保代码示例符合Java语法,使用泛型,并且处理可能的异常情况。 最后,检查分页逻辑是否正确,特别是结束索引的计算,避免索引越界。同时,考虑性能问题,比如在处理大数据量时,分片是否能有效减少内存占用或提高处理效率。可能还需要提到使用流式处理或并行处理来优化性能,如引用[1]提到的并行处理。 总结步骤: 1. 实现一个分片工具方法,使用subList进行分割。 2. 处理边界条件,确保结束索引不超过列表大小。 3. 提供示例代码,展示如何使用该方法。 4. 扩展说明如何结合Spring Batch或BulkRequest进行批处理。 5. 引用相关参考资料,如Spring Batch的ItemReader或BulkRequest的使用。 需要确保回答结构清晰,代码正确,并且覆盖用户可能的深层需求,比如处理大数据集时的效率问题。</think>### 分片处理List数据的Java实现方法 #### 1. 核心分片逻辑实现 使用 `List.subList()` 方法实现分片,核心步骤如下: ```java public static <T> List<List<T>> partitionList(List<T> list, int batchSize) { List<List<T>> partitions = new ArrayList<>(); int total = list.size(); for (int i = 0; i < total; i += batchSize) { int end = Math.min(i + batchSize, total); partitions.add(list.subList(i, end)); } return partitions; } ``` #### 2. 调用示例(每组30条) ```java List<Integer> dataList = new ArrayList<>(Arrays.asList(1,2,3,...,900)); List<List<Integer>> batches = partitionList(dataList, 30); // 批量处理示例 batches.forEach(batch -> { System.out.println("Processing batch: " + batch); // 调用批处理接口(如数据库批量插入) }); ``` #### 3. 结合批处理框架的优化 - **Spring Batch集成**:通过 `JdbcCursorItemReader` 分页读取数据[^2] - **Elasticsearch场景**:使用 `BulkRequest` 封装批量请求[^3] ```java // Elasticsearch批量处理示例 BulkRequest bulkRequest = new BulkRequest(); batches.forEach(batch -> { batch.forEach(item -> { bulkRequest.add(new IndexRequest("index_name").source(item)); }); }); client.bulk(bulkRequest, RequestOptions.DEFAULT); ``` #### 4. 性能优化建议 - 使用并行流加速处理(注意线程安全): ```java batches.parallelStream().forEach(this::processBatch); ``` - 对超过10万条数据建议采用数据库分页查询代替内存分片[^4] - 大数据量场景可结合索引优化(如覆盖索引)[^5] #### 5. 异常处理建议 ```java try { batches.forEach(batch -> { if (!batch.isEmpty()) { repository.batchInsert(batch); // 批量写入示例 } }); } catch (BatchUpdateException e) { // 实现失败重试或补偿机制 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liu.kai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值