解决get提交数据量太大的问题

本文介绍了一种解决因Base64编码图片数据过大而导致GET请求失败的方法,通过转换为POST请求来规避大小限制,并提供了具体的JavaScript实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于参数中是base64编码后的图片数据,图片比较大,导致get请求失败,提示数据太大。

get最大是256b,post是2M。

解决方式:

使用伪post方式:


//上传图片方法
function picUpload(){
var ocrImageSrc = document.querySelector('#ocr_img').childNodes[0].src;
//window.parent.self.open(encodeURI((hostUrl+"?reportlet=/CRM/联系人新建_名片信息录入.cpt&op=write&photo="+ocrImageSrc)),"_self");
openPostWindow(encodeURI(hostUrl+"?reportlet=/CRM/联系人新建_名片信息录入.cpt&op=write"),encodeURI(ocrImageSrc),'_parent');
//alert(encodeURI((hostUrl+"?reportlet=/CRM/联系人新建_名片信息录入.cpt&op=write&photo=")));

}


/**
 * 使用post方式打开画面,解决self.open传输数据get方法的传输数据量限制
 */
function openPostWindow(url, data, name)     
  
  {     
  
     var tempForm = document.createElement("form");     
  
     tempForm.id="tempForm1";     
  
     tempForm.method="post";     
  
     tempForm.action=url;     
  
     tempForm.target=name;     
  
     
  
     var hideInput = document.createElement("input");     
  
     hideInput.type="hidden";     
  
     hideInput.name= "photo"  
  
     hideInput.value= data;   
  
     tempForm.appendChild(hideInput);      
  
     tempForm.addEventListener("onsubmit",function(){ openWindow(url,name); });   
  
     document.body.appendChild(tempForm);     
  
  
  
     fireEvent(tempForm,"onsubmit");   
  
     tempForm.submit();   
  
     document.body.removeChild(tempForm);   
  
}   
  
  
/**
 * 打开画面
 */
function openWindow(url,name)     
  
{     
  
     self.open(url,name,'height=400, width=400, top=0, left=0, toolbar=yes, menubar=yes, scrollbars=yes, resizable=yes,location=yes, status=yes');      
  
}   


------------------------------------------------------------------------------------------------------------------------------------------------------------------------

重点:可以使用AJAX POST跨域方式,详情请见:http://blog.youkuaiyun.com/danfeixia/article/details/71599304


<think>好的,用户问的是Java多线程分批次存储量数据到数据库。我需要先理清楚这个问题涉及的各个方面。首先,用户可能面对的是需要处理量数据,比如从文件、消息队列或者其他数据源读取的数据,然后高效地存入数据库。直接单线程处理可能效率不够,所以要用多线程和分批次的方式来优化。 接下来,我得考虑多线程的基本实现方式。Java里常用的有线程池,比如ExecutorService,这样可以管理线程资源,避免频繁创建销毁线程的开销。分批次的话,可能需要把数据分成小块,每个线程处理一批,然后批量插入数据库,减少IO次数。 然后要考虑数据库方面的优化。比如使用JDBC的批量操作addBatch和executeBatch,或者ORM框架如MyBatis的批量支持。事务管理也很重要,可能需要每个批次一个事务,避免事务导致锁等问题。 还有数据分片的策略,如何均匀分配数据到各个线程,避免有的线程处理太多,有的太少。可能需要对数据列表进行划分,比如用subList方法分块。 线程间的协调和错误处理也不能忽视。比如,如何处理某个批次插入失败的情况,是否需要重试或者记录日志。还有并发控制,确保数据库连接不被耗尽,可能需要使用连接池配置合理的最连接数。 另外,需要考虑数据库的承受能力,虽然多线程可以提高速度,但过多并发可能会压垮数据库,所以需要测试找到合适的线程数和批次小。可能还需要使用CountDownLatch或CyclicBarrier来同步线程,确保所有数据处理完成后再继续后续操作。 最后,性能监控和调优也是必要的,比如记录每个批次的处理时间,调整参数。可能还要考虑数据顺序是否重要,如果不需要保持顺序,可以更自由地分片;如果需要,则可能得按顺序处理批次。 总结下来,整个流程应该是:数据分片→线程池处理→批量插入→事务控制→错误处理→性能调优。需要分步骤释,并给出示例代码,帮助用户理具体实现。同时提醒注意事项,比如资源管理、线程安全、数据库配置等。</think>以下分步骤介绍Java多线程分批次存储量数据到数据库的实现方案: --- ### 一、核心实现思路 1. **数据分片**:将原始数据分割为多个子批次 2. **线程池管理**:通过线程池控制并发规模 3. **批量提交**:利用JDBC批量操作提升效率 4. **事务控制**:合理管理事务边界 5. **异常处理**:保证数据一致性和可靠性 --- ### 二、具体实现步骤 #### 1. 准备线程池 ```java int corePoolSize = Runtime.getRuntime().availableProcessors() * 2; ExecutorService executor = Executors.newFixedThreadPool(corePoolSize); ``` #### 2. 数据分片算法 ```java // 原始数据集合 List<Data> allData = fetchDataFromSource(); // 分片小(建议500-2000条/批次) int batchSize = 1000; // 计算分片数量 int total = allData.size(); int batchCount = (total + batchSize - 1) / batchSize; // 创建分片任务 List<Callable<Integer>> tasks = new ArrayList<>(); for (int i = 0; i < batchCount; i++) { int from = i * batchSize; int to = Math.min((i + 1) * batchSize, total); List<Data> subList = allData.subList(from, to); tasks.add(new BatchInsertTask(subList)); } ``` #### 3. 批量插入任务类 ```java class BatchInsertTask implements Callable<Integer> { private final List<Data> batchData; public BatchInsertTask(List<Data> data) { this.batchData = data; } @Override public Integer call() { try (Connection conn = dataSource.getConnection()) { conn.setAutoCommit(false); String sql = "INSERT INTO table (...) VALUES (...)"; try (PreparedStatement ps = conn.prepareStatement(sql)) { for (Data item : batchData) { ps.setString(1, item.getValue1()); ps.setInt(2, item.getValue2()); ps.addBatch(); } int[] results = ps.executeBatch(); conn.commit(); return Arrays.stream(results).sum(); } } catch (SQLException e) { // 处理回滚和重试逻辑 return 0; } } } ``` #### 4. 执行并监控任务 ```java List<Future<Integer>> futures = executor.invokeAll(tasks); // 统计执行结果 int totalInserted = 0; for (Future<Integer> future : futures) { totalInserted += future.get(); } executor.shutdown(); ``` --- ### 三、关键优化点 1. **连接池配置**: ```properties # 建议配置(以HikariCP为例) maximumPoolSize=20 connectionTimeout=30000 maxLifetime=1800000 ``` 2. **批次小调整**: - 根据数据库类型调整(MySQL建议1000条/批次) - 通过压力测试寻找最优值 3. **异常处理策略**: ```java // 重试机制示例 int retryCount = 0; while (retryCount < MAX_RETRY) { try { // 执行插入 break; } catch (SQLException e) { retryCount++; Thread.sleep(1000 * retryCount); } } ``` --- ### 四、注意事项 1. **线程安全**: - 每个线程使用独立的Connection - 避免共享非线程安全对象 2. **资源控制**: - 限制最线程数(通常建议CPU核数*2 ~ *4) - 监控数据库连接数 3. **事务隔离**: - 每个批次独立事务 - 避免长时间持有事务 4. **性能监控**: ```java // 添加监控埋点 long start = System.currentTimeMillis(); // ...执行插入... long cost = System.currentTimeMillis() - start; metrics.recordInsertTime(cost); ``` --- ### 五、扩展方案 1. **生产级方案建议**: ```mermaid graph TD A[数据源] --> B[缓冲队列] B --> C{线程池} C --> D[批量插入] D --> E[成功日志] D --> F[死信队列] ``` 2. **高级特性整合**: - Spring Batch框架 - 事务模板(TransactionTemplate) - 响应式编程(WebFlux + R2DBC) --- 通过合理配置线程池、优化批次小、严格控制事务边界,该方案可实现每小时数百万条数据的高效入库。实际应用中建议结合具体数据库类型(MySQL/Oracle等)进行参数调优。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值