package com.zy.acs.manager.manager.controller.utils; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.fastjson.JSON; import com.google.common.collect.Lists; import com.zy.acs.common.utils.GsonUtils; import com.zy.acs.framework.common.Cools; import com.zy.acs.manager.manager.entity.Code; import com.zy.acs.manager.manager.entity.CodeGap; import com.zy.acs.manager.manager.entity.Route; import com.zy.acs.manager.manager.service.CodeGapService; import com.zy.acs.manager.manager.service.CodeService; import com.zy.acs.manager.manager.service.RouteService; import lombok.extern.slf4j.Slf4j; import java.util.*; @Slf4j public class MapDataListener implements ReadListener> { /** * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收 */ private static final int BATCH_COUNT = 10000; private List> cachedDataList = Lists.newArrayListWithExpectedSize(BATCH_COUNT); /** * 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。 */ private RouteService routeService; private CodeService codeService; private CodeGapService codeGapService; private List codes = new ArrayList<>(); private List routes = new ArrayList<>(); private List codeGaps = new ArrayList<>(); /** * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来 * * @param routeService */ public MapDataListener(RouteService routeService, CodeService codeService, CodeGapService codeGapService) { this.routeService = routeService; this.codeService = codeService; this.codeGapService = codeGapService; } /** * 这个每一条数据解析都会来调用 * * @param data one row value. It is same as {@link AnalysisContext#readRowHolder()} * @param context */ @Override public void invoke(Map data, AnalysisContext context) { log.info("解析到一条数据:{}", JSON.toJSONString(data)); cachedDataList.add(data); // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM if (cachedDataList.size() >= BATCH_COUNT) { saveData(); // 存储完成清理 list cachedDataList = Lists.newArrayListWithExpectedSize(BATCH_COUNT); } } /** * 所有数据解析完成了 都会来调用 * * @param context */ @Override public void doAfterAllAnalysed(AnalysisContext context) { // 这里也要保存数据,确保最后遗留的数据也存储到数据库 Map xData = cachedDataList.get(78); Map x = new HashMap<>(); xData.entrySet().forEach(entry -> { x.put(entry.getKey() , entry.getValue()); }); Map y = new HashMap<>(); for (int i = 0; i < cachedDataList.size(); i++) { Map integerStringMap = cachedDataList.get(i); y.put(i, integerStringMap.get(1)); } log.info("x轴:{}", JSON.toJSONString(x)); log.info("y轴:{}", JSON.toJSONString(y)); for (int i = 0; i < cachedDataList.size(); i++) { if (i >= 78) { continue; } Map integerStringMap = cachedDataList.get(i); int finalI = i; integerStringMap.entrySet().forEach(entry -> { if (entry.getValue() != null && entry.getValue().startsWith("00")) { log.info("数据:{}", entry.getValue()); Code code = new Code(); code.setData(entry.getValue()); code.setUuid("code".concat(code.getData())); if (x.get(entry.getKey()) == null) { log.info("x轴数据为空:{}", entry.getKey()); } code.setX(Double.parseDouble(x.get(entry.getKey()))+10000); if (y.get(finalI) == null) { log.info("y轴数据为空:{},{}", finalI, y.get(finalI)); } code.setY(Double.parseDouble(y.get(finalI))+10000); code.setScale(GsonUtils.toJson(Cools.add("x", 1).add("y", 1))); code.setCreateTime(new Date()); code.setUpdateTime(new Date()); codes.add(code); } }); } //log.info("所有数据解析完成!{}", JSON.toJSONString(codes)); log.info("所有数据解析完成!{}", codes.size()); saveData(); } /** * 加上存储数据库 */ private void saveData() { log.info("{}条数据,开始存储数据库!", cachedDataList.size()); for (Code code : codes){ codeService.save(code); } log.info("存储数据库成功!"); } }