您的位置:首页 > 新闻 > 会展 > 万能转账生成器app_北京一诺互联科技有限公司_推广营销是什么_优化网站建设seo

万能转账生成器app_北京一诺互联科技有限公司_推广营销是什么_优化网站建设seo

2024/12/27 7:30:38 来源:https://blog.csdn.net/m0_50707445/article/details/144747169  浏览:    关键词:万能转账生成器app_北京一诺互联科技有限公司_推广营销是什么_优化网站建设seo
万能转账生成器app_北京一诺互联科技有限公司_推广营销是什么_优化网站建设seo

在工作需求中遇到了一个导入客户数据的需求,因为项目本身使用若依框架,所以直接使用了若依框架自带的easypoi进行导出.
但是后续发现,easypoi在数据量较大的时候会占用非常多的内存,导入10M的excel,占用内存接近1G,这是不可接受的.所以后续先是优化成了阿里的easyExcel,easyExcel对内存方面进行了优化,分片操作,提升了内存和速度,整体要比easypoi优秀很多.代码为:

    @RepeatSubmit@ApiOperation("2.3.2个人线索excel导入")@PostMapping("/importClue")public R importClue(@RequestPart("file") MultipartFile file) throws Exception {Long userId = SecurityUtils.getUserId();// 使用 EasyExcel 读取数据ClientImportDTOListener listener = new ClientImportDTOListener();EasyExcel.read(file.getInputStream(), ClientImportDTO.class, listener).sheet().doRead();// 获取所有数据List<ClientImportDTO> userList = listener.getAllDataList()}
@Slf4j
public class ClientImportDTOListener implements ReadListener<ClientImportDTO> {private static final int BATCH_COUNT = 50;private List<ClientImportDTO> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);@Getterprivate List<ClientImportDTO> allDataList = new ArrayList<>();private static final int MAX_RECORD_COUNT = 20000; // 最大记录数private int totalRecordCount = 0; // 记录总数public void invoke(ClientImportDTO data, AnalysisContext context) {totalRecordCount++;  // 计数每一条记录// 如果总记录数超过2万条,抛出异常并停止读取
//        if (totalRecordCount > MAX_RECORD_COUNT) {
//            throw new IllegalArgumentException("数据超过两万条, 请拆分至两万条以内, 分批上传!");
//        }// 将数据缓存到临时列表中cachedDataList.add(data);// 如果缓存达到批次大小,将数据加入到 allDataList 中,并清空缓存if (cachedDataList.size() >= BATCH_COUNT) {allDataList.addAll(cachedDataList);cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {allDataList.addAll(cachedDataList);log.info("所有数据解析完成,收集到 {} 条数据", allDataList.size());}}@Data
@AllArgsConstructor
@NoArgsConstructor
public class ClientImportDTO {@Excel(name = "客户姓名")@ExcelProperty("客户姓名")private String name;@Excel(name = "手机号")@ExcelProperty("手机号")private String phone;@Excel(name = "获客渠道")@ExcelProperty("获客渠道")private String source;
}

这里因为篇幅原因,删除了部分ClientImportDTO 的字段.这里也不是重点.
然后在导入接口处打了日志.发现把excel转对象确实非常快,2万条只要1秒左右,但是转成对象之后保存数据库还有大量的逻辑,这样的逻辑导致接口速度非常的慢,2万条要2分钟才能响应,对应前端就是用户在导入之后要转圈两三分钟才能获取到导入成功的结果,整体体验较差.
于是在这里又进行了进一步的优化,这里采用的方案是事件发布机制.
创建一个监听者,监听导入事件的发布,在导入接口从excel转换为对象列表之后触发该事件,监听者监听到该事件,然后去触发导入的逻辑操作,从而实现后台录入数据并分配,前台直接返回数据操作中,并通过消息来返回结果.
具体代码为:

    @RepeatSubmit@ApiOperation("2.3.2个人线索excel导入")@PostMapping("/importClue")public R importClue(@RequestPart("file") MultipartFile file) throws Exception {Long userId = SecurityUtils.getUserId();// 使用 EasyExcel 读取数据ClientImportDTOListener listener = new ClientImportDTOListener();EasyExcel.read(file.getInputStream(), ClientImportDTO.class, listener).sheet().doRead();// 获取所有数据List<ClientImportDTO> userList = listener.getAllDataList();// 调用异步方法发布事件clueService.importBatch2AsyncclueAsyncService.importClueAsync(userList, userId);return R.ok(null,"数据导入已开始,处理过程将在后台完成!");}

在这个过程中,又出现了循环依赖的问题,因为启动项目的载入顺序,导致无法获取到对应的service,后来的解决方案是采用构造器注入.
对应的异步service为:

@Service
public class ClueAsyncService {private final ApplicationEventPublisher eventPublisher;@Autowiredpublic ClueAsyncService(ApplicationEventPublisher eventPublisher) {this.eventPublisher = eventPublisher;}/*** 异步导入个人线索*/@Asyncpublic void importClueAsync(List<ClientImportDTO> userList, Long loginId) {// 发布事件,触发异步处理ImportClueEvent event = new ImportClueEvent(this, userList, loginId);eventPublisher.publishEvent(event);}
}

监听器代码:

@Component
public class ImportClueEventListener {
@Resource
private ClueService clueService;@Async@Transactional(rollbackFor = Exception.class)@EventListenerpublic void handleImportClueEvent(ImportClueEvent event) {// 获取事件数据List<ClientImportDTO> userList = event.getUserList();Long loginId = event.getLoginId();// 执行实际的异步处理逻辑,此时你可以在此方法内部调用同步方法clueService.importBatch2Async(userList,loginId);}
}

这样就能够保证监听,触发,执行逻辑的逻辑通顺.而用户会在很快的时间内直接返回"数据导入已开始,处理过程将在后台完成!".结果通过websocket发送到消息中:
在这里插入图片描述
该方法适用于不仅导入数据量大,导入后逻辑还复杂的场景.
如果仅仅是导入数据量大,但无后续复杂逻辑,直接入库,则不需要使用该方法,直接easyExcel再配上分次批量存储即可.

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com