写点什么

商品中心—商品考核系统的技术文档(二)

  • 2025-06-17
    福建
  • 本文字数:25520 字

    阅读完需:约 84 分钟

6.商品生命周期系统的定时考核任务


(1)定时任务处理考核指标数据的设计


定时任务会根据考核指标数据,计算出商品的考核结果。定时查询出考核指标数据,根据商品质量、诚信、销量、利润等数据,分别对试销期和滞销期商品进⾏考核,并将考核结果写⼊考核结果缓冲表。

 

在⼀轮考核任务中,对于配置了⽩名单的品类商品,可以免除本轮次考核,免除本轮次考核的考核状态为免考核。

 

质量和诚信问题,具有⼀票否决权,⼆者任⼀不满⾜,则本轮考核不通过。滞销期考核也直接不通过,考核状态为考核不通过。

 

销售⽐率、利润率、退货⽐率、客诉率、损耗率五个考核指标,通过率未超过考核指标配置的考核通过率,则本轮考核不通过。此时状态是考核中,需⽐较连续失败次数是否超过阈值,来决定考核不通过。

 

对于试销期商品,本轮考核不通过则该商品直接考核不通过。对于滞销期商品,本轮考核不通过需⽐较考核指标配置的连续失败次数,只有达到了配置的连续失败次数,才会考核不通过。如果没有达到连续失败次数,则对该数值进⾏累加,然后等待下⼀轮考核。

 

当本轮次考核结束,会将计算得到的考核结果写⼊考核结果缓冲表。同时让该考核指标数据失效,避免下⼀轮重复拉取该考核指标数据。

 

(2)定时任务处理考核指标数据的实现


一.任务执⾏说明


考核任务的周期在 xxljob 的管理界⾯中指定,并且调度任务时需传⼊参数。参数要指定该任务的考核类型,是试销期考核还是滞销期考核,不传⼊参数指定考核类型则会抛出异常。

 

二.任务流程图



三.任务具体实现


步骤一:查询大数据系统计算出来的商品考核指标数据步骤二:考核指标数据对应的商品的生命周期与考核类型对比步骤三:过滤出在白名单中免考核的考核指标数据步骤四:过滤出有质量或者诚信问题的商品指标数据步骤五:分页查询出考核配置数据步骤六:对商品指标数据进行考核以及划分结果步骤七:商品考核数据分多种类别写入结果缓冲表步骤八:将参与本轮考核计算的考核指标数据都设置为失效状态
复制代码


//生命周期阶段考核@Componentpublic class CalculateExpriResultSchedule {    //考核结果资源管理    @Autowired    private ItemExpriResultRepository itemExpriResultRepository;
//生命周期资源管理 @Autowired private ItemPeriodStageRepository itemPeriodStageRepository;
//考核白名单资源管理 @Autowired private CategoryExpriWhiteRepository categoryExpriWhiteRepository;
//商品考核资源管理 @Autowired private ProductExpriRepository productExpriRepository;
//考核结果对象克隆 @Resource private ItemExpriResultConverter itemExpriResultConverter;
//MQ producer @Autowired private DefaultProducer defaultProducer;
//定时任务:根据商品的质量和诚信问题、销量、客诉率等数据,对试销期、成熟期商品进行考核,并将考核结果写入考核结果缓冲表 //一般情况下:每天凌晨3点钟执行 @XxlJob("assessing") @Transactional(rollbackFor = Exception.class) public void assessing() { //1.获取考核类型参数(试销期1,成熟期2) Integer assessmentType = getAssessmentType(); //2.查询大数据系统计算出来的商品考核指标数据 List<ProductExpriDataResultDTO> totalExpriDataList = productExpriRepository.listExpriDataResultByPage(assessmentType); //3.考核指标数据对应的itemIdList List<String> itemIdList = getItemIdList(totalExpriDataList); //4.考核指标数据对应的categoryIdList List<Integer> categoryIdList = getCategoryIdList(totalExpriDataList); //5.查询生命周期阶段 Map<String, ItemPeriodStageDTO> itemPeriodStageMap = listItemPeriodStageByPage(assessmentType, itemIdList); //6.过滤掉商品所处生命周期阶段和当前考核类型不匹配的数据,并返回生命周期阶段Map totalExpriDataList = filterPeriodConsistencyToMap(totalExpriDataList, itemPeriodStageMap); //7.过滤出在白名单中免考核的考核指标数据 List<ProductExpriDataResultDTO> nonAssessmentExpriDataList = filterNonAssessmentToList(totalExpriDataList, categoryIdList); //8.分页查询出考核配置数据 Map<Integer, ProductExpriConfigurationDTO> expriConfigurationMap = listExpriConfigurationByPage(categoryIdList, assessmentType); //9.批量查质量或诚信问题数据,并过滤出存在质量或诚信问题,考核不通过的数据 List<ProductExpriDataResultDTO> assessFailureList = filterConformingIntegrityRecordToList(totalExpriDataList, itemIdList); //10.比较销售额和销售率、客诉率等考核指标项,将考核数据分别划分到:考核不通过、考核通过、考核中三个集合中 List<ProductExpriDataResultDTO> assessingList = filterSalesVolumePassTargetToList(totalExpriDataList, assessFailureList, expriConfigurationMap, assessmentType); //11.将考核不通过、考核中、考核通过,免考核的考核指标数据,批量写入到考核结果缓冲表 batchInsertAssessmentResult(itemIdList, assessFailureList, assessingList, totalExpriDataList, nonAssessmentExpriDataList, itemPeriodStageMap); //12.将参与本轮考核计算的考核指标数据都设置为失效状态 batchInvalidExpriData(itemIdList); } ...}
复制代码


步骤一:查询大数据系统计算的商品考核指标数据


//商品考核资源管理@Repositorypublic class ProductExpriRepository {    ...    //分页查询某考核类型下所有生效的商品考核指标数据    public List<ProductExpriDataResultDTO> listExpriDataResultByPage(Integer assessmentType) {        //构造查询条件        LambdaQueryWrapper<ProductExpriDataResultDO> queryWrapper = Wrappers.lambdaQuery();        //是否生效        queryWrapper.eq(ProductExpriDataResultDO::getIsEffective, YesOrNoEnum.YES.getCode());        //是否删除        queryWrapper.eq(ProductExpriDataResultDO::getDelFlag, YesOrNoEnum.YES.getCode());        //考核类型:试销期考核/成熟期考核        queryWrapper.eq(ProductExpriDataResultDO::getAssessmentType, assessmentType);
//分页查询存放数据的总集合 List<ProductExpriDataResultDO> results = new ArrayList<>();
int pageNum = 1; //设置每次查询的数据量,最大为200 int pageSize = ProductConstants.QUERY_ITEM_MAX_COUNT; Page<ProductExpriDataResultDO> page = new Page<>(pageNum, pageSize); //查询第一页数据 Page<ProductExpriDataResultDO> pageResult = productExpriDataResultMapper.selectPage(page, queryWrapper); //判断是否还有数据,还有数据则页码 + 1继续执行分页查询 List<ProductExpriDataResultDO> batchResult = pageResult.getRecords(); try { while (pageNum <= pageResult.getTotal()) { results.addAll(batchResult); pageNum += 1; page.setCurrent(pageNum); pageResult = productExpriDataResultMapper.selectPage(page, queryWrapper); batchResult = pageResult.getRecords(); //每次循环获取数据后,休眠20ms,避免对数据库造成太大压力 Thread.sleep(20); } } catch (InterruptedException e) { throw new BaseBizException(ProductExceptionCode.PRODUCT_SQL); }
//最后一组数据也放入结果集中 results.addAll(page.getRecords()); //转为DTO List<ProductExpriDataResultDTO> productExpriDataResultList = productExpriDataResultConverter.listEntityToDTO(results); return Objects.isNull(productExpriDataResultList) ? Lists.newArrayList() : productExpriDataResultList; } ...}
复制代码


步骤二:考核指标数据对应的商品的生命周期与考核类型对比


@Componentpublic class CalculateExpriResultSchedule {    ...    //过滤掉所处的生命周期阶段和当前考核类型不匹配的数据    //@param totalExpriDataList 考核指标数据集合    //@param itemPeriodStageMap 生命周期Map,key为itemId    //@return 生命周期阶段和考核类型匹配的考核指标数据集合    private List<ProductExpriDataResultDTO> filterPeriodConsistencyToMap(List<ProductExpriDataResultDTO> totalExpriDataList, Map<String, ItemPeriodStageDTO> itemPeriodStageMap) {        //过滤考核指标数据        totalExpriDataList = totalExpriDataList.stream()            .filter(productExpriDataResultDTO -> Objects.nonNull(itemPeriodStageMap.get(productExpriDataResultDTO.getItemId())))            .collect(Collectors.toList());        return totalExpriDataList;    }    ...}
复制代码


步骤三:过滤出在白名单中免考核的考核指标数据


@Componentpublic class CalculateExpriResultSchedule {    ...    //过滤出在白名单中的考核指标数据    //@param totalExpriDataList 考核指标数据集合    //@return 在白名单中的考核指标数据集合    private List<ProductExpriDataResultDTO> filterNonAssessmentToList(List<ProductExpriDataResultDTO> totalExpriDataList, List<Integer> categoryIdList) {        //1.分页查询出考核指标数据中对应的白名单所属的categoryIdList        List<Integer> whiteCategoryIdList = categoryExpriWhiteRepository.queryExpriWhiteByCategoryIdList(categoryIdList);        //2.过滤出在白名单范围内的考核指标数据        List<ProductExpriDataResultDTO> nonAssessmentExpriDataList = totalExpriDataList.stream()            .filter(productExpriDataResultDTO -> whiteCategoryIdList.contains(productExpriDataResultDTO.getCategoryId()))            .collect(Collectors.toList());        //3.剔除掉在白名单范围内的考核指标数据        totalExpriDataList.removeAll(nonAssessmentExpriDataList);        //4.返回在白名单内的考核指标数据        return nonAssessmentExpriDataList;    }    ...}
//考核白名单资源管理@Repositorypublic class CategoryExpriWhiteRepository { ... //分页查询出categoryIdList对应的白名单集合 //@param categoryIdList 品类ID集合 //@return 处于白名单范围内的categoryIdList public List<Integer> queryExpriWhiteByCategoryIdList(List<Integer> categoryIdList) { //处于白名单范围内的categoryIdList List<Integer> whiteCategoryIdList = new ArrayList<>(); //一次最大查询200个数据,多个分页查询,这里做数据切割 List<List<Integer>> splitList = DataCuttingUtil.dataCuttingString(categoryIdList, ProductConstants.QUERY_ITEM_MAX_COUNT); for (List<Integer> categoryIds : splitList) { LambdaQueryWrapper<CategoryExpriWhiteDO> queryWrapper = Wrappers.lambdaQuery(); queryWrapper.in(CategoryExpriWhiteDO::getCategoryId, categoryIds); queryWrapper.eq(CategoryExpriWhiteDO::getDelFlag, YesOrNoEnum.YES.getCode()); queryWrapper.eq(CategoryExpriWhiteDO::getActiveFlag, YesOrNoEnum.YES.getCode()); //分批次查询出categoryIdList对应的白名单集合 List<CategoryExpriWhiteDO> categoryResultList = categoryExpriWhiteMapper.selectList(queryWrapper); if (!CollectionUtils.isEmpty(categoryResultList)) { whiteCategoryIdList.addAll(categoryResultList.stream().map(CategoryExpriWhiteDO::getCategoryId).collect(Collectors.toList())); } } return whiteCategoryIdList; } ...}
复制代码


步骤四:过滤出有质量或者诚信问题的商品指标数据


@Componentpublic class CalculateExpriResultSchedule {    ...    //批量查询出质量或诚信问题数据集合,并对比考核数据,将对应的考核数据添加到考核不通过的集合中    //@param totalExpriDataList 考核结果数据    //@param itemIdList         商品ID集合    //@return 考核不通过考核指标数据集合    private List<ProductExpriDataResultDTO> filterConformingIntegrityRecordToList(List<ProductExpriDataResultDTO> totalExpriDataList, List<String> itemIdList) {        //批量查询出质量诚信问题数据集合        List<ProductBadIssuesResultDTO> productBadIssuesResultList = productExpriRepository.queryProductBadIssuesResultByItemIdList(itemIdList);        //List转为Map,itemId作为key        Map<String, ProductBadIssuesResultDTO> productBadIssuesResultMap = productBadIssuesResultList.stream()            .collect(Collectors.toMap(ProductBadIssuesResultDTO::getItemId, productBadIssuesResult -> productBadIssuesResult, (oldKey, newKey) -> oldKey));        //过滤出存在质量问题的考核指标数据        List<ProductExpriDataResultDTO> assessFailureList = totalExpriDataList.stream().filter(productExpriDataResultDTO -> {            //根据考核结果数据的itemId获取质量、诚信问题记录            ProductBadIssuesResultDTO productBadIssuesResult = productBadIssuesResultMap.get(productExpriDataResultDTO.getItemId());            //如果该考核结果数据存在质量诚信问题,就保留,否则就过滤掉            if (productBadIssuesResult == null) {                return false;            }            if (productBadIssuesResult.getContractIntegrity().equals(YesOrNoEnum.YES.getCode()) &&                productBadIssuesResult.getNonConformingProduct().equals(YesOrNoEnum.YES.getCode())) {                return false;            }            return true;        }).collect(Collectors.toList());        //剔除掉在存在质量问题的考核指标数据        totalExpriDataList.removeAll(assessFailureList);        //返回考核不通过的考核指标数据        return assessFailureList;    }    ...}
复制代码


步骤五:分页查询出考核配置数据


@Componentpublic class CalculateExpriResultSchedule {    ...    //分页查考核配置数据    //@param categoryIdList 品类ID集合    //@return 封装为Map,categoryId作为key    private Map<Integer, ProductExpriConfigurationDTO> listExpriConfigurationByPage(List<Integer> categoryIdList, Integer assessmentType) {        //分页查询出考核配置数据        List<ProductExpriConfigurationDTO> productExpriConfigurationList = productExpriRepository.queryExpriConfigurationByCategoryIdList(categoryIdList, assessmentType);        //List转为Map,categoryId作为key        Map<Integer, ProductExpriConfigurationDTO> productExpriConfigurationMap = productExpriConfigurationList.stream()            .collect(Collectors.toMap(ProductExpriConfigurationDTO::getCategoryId, productExpriConfiguration -> productExpriConfiguration, (oldKey, newKey) -> oldKey));        return productExpriConfigurationMap;    }    ...}
//商品考核资源管理@Repositorypublic class ProductExpriRepository { ... //分页查询出categoryIdList对应的考核配置集合 //@param categoryIdList 品类ID集合 //@return 考核配置集合 public List<ProductExpriConfigurationDTO> queryExpriConfigurationByCategoryIdList(List<Integer> categoryIdList, Integer assessmentType) { //考核配置集合 List<ProductExpriConfigurationDTO> productExpriConfigurationList = new ArrayList<>(); //一次最大查询200个数据,多个分页查询,这里做数据切割 List<List<Integer>> splitList = DataCuttingUtil.dataCuttingString(categoryIdList, ProductConstants.QUERY_ITEM_MAX_COUNT); for (List<Integer> categoryIds : splitList) { LambdaQueryWrapper<ProductExpriConfigurationDO> queryWrapper = Wrappers.lambdaQuery(); queryWrapper.in(ProductExpriConfigurationDO::getCategoryId, categoryIds); queryWrapper.eq(ProductExpriConfigurationDO::getDelFlag, YesOrNoEnum.YES.getCode()); queryWrapper.eq(ProductExpriConfigurationDO::getAssessmentType, assessmentType); //分批次查询出categoryIdList对应的考核配置集合 List<ProductExpriConfigurationDO> configurationResultList = productExpriConfigurationMapper.selectList(queryWrapper); if (!CollectionUtils.isEmpty(configurationResultList)) { productExpriConfigurationList.addAll(productExpriConfigurationConverter.listEntityToDTO(configurationResultList)); } } return productExpriConfigurationList; } ...}
复制代码


步骤六:对商品指标数据进行考核以及划分结果


@Componentpublic class CalculateExpriResultSchedule {    ...    //比较考核结果数据和考核配置数据,判断考核结果数据是否通过考核    //销售额数据未达到要求,本轮考核不通过    //销售比率、客诉率、损耗率等5项指标,达到要求的指标数量未超过考核配置中通过考核的指标数量,本轮考核不通过    //对于试销期考核,本轮考核不通过,则考核状态即为不通过    //但是对于滞销期考核,本轮考核不通过,还需要比较考核配置中的连续失败次数    //如果连续失败次数超过了配置中的数值,则考核不通过    //否则,对连续失败次数进行累加操作,考核状态为考核中    //@param totalExpriDataList    考核指标数据(所有的考核数据集合)    //@param assessFailureList     考核未通过的考核指标数据    //@param expriConfigurationMap 考核指标配置    //@param assessmentType        考核类型    //@return 考核中的考核指标数据    private List<ProductExpriDataResultDTO> filterSalesVolumePassTargetToList(List<ProductExpriDataResultDTO> totalExpriDataList,        List<ProductExpriDataResultDTO> assessFailureList, Map<Integer, ProductExpriConfigurationDTO> expriConfigurationMap, Integer assessmentType) {        //考核中的考核指标数据集合        List<ProductExpriDataResultDTO> assessingList = new ArrayList<>();        //批量查询出连续失败次数,作为Map,id是itemId        Map<String, Integer> failTimesMap = itemExpriResultRepository.listFailTimesByPage();        for (ProductExpriDataResultDTO expriResult : totalExpriDataList) {            //考核指标数据对应的考核配置            ProductExpriConfigurationDTO expriConfiguration = expriConfigurationMap.get(expriResult.getCategoryId());            //是否低于最低销售额            if (expriResult.getSalesVolume() < expriConfiguration.getSalesVolume()) {                fillListByAssessmentType(assessFailureList, assessingList, failTimesMap, assessmentType, expriResult, expriConfiguration);            }            //销售比率、客诉率、退货率是否符合要求            if (!checkAssessment(expriResult, expriConfiguration)) {                fillListByAssessmentType(assessFailureList, assessingList, failTimesMap, assessmentType, expriResult, expriConfiguration);            }        }        //剔除掉考核不通过的考核指标数据        totalExpriDataList.removeAll(assessFailureList);        //剔除掉考核中的考核指标数据        totalExpriDataList.removeAll(assessingList);        //考核的流程执行到这里,totalExpriDataList中剩下的就是考核成功的考核指标数据        //返回考核中的考核指标数据        return assessingList;    }
//检查客诉率、退货率的指标是否符合要求 //@param expriData 考核指标数据 //@param expriConfiguration 考核指标配置 //@return true:符合;false:不符合 private boolean checkAssessment(ProductExpriDataResultDTO expriData, ProductExpriConfigurationDTO expriConfiguration) { //考核通过指标数量 Integer passTargetConfig = expriConfiguration.getPassTarget(); Integer passTarget = 0; //销售比例配置 Integer soldPropotionConfig = expriConfiguration.getSoldPropotion(); Integer soldPropotion = expriData.getSoldPropotion(); if (soldPropotion >= soldPropotionConfig) { passTarget++; } //每单利润率配置 Integer orderProfitMarginConfig = expriConfiguration.getOrderProfitMargin(); Integer orderProfitMargin = expriData.getOrderProfitMargin(); if (orderProfitMargin >= orderProfitMarginConfig) { passTarget++; } //退货比率配置 Integer returnRateConfig = expriConfiguration.getReturnRate(); Integer returnRate = expriData.getReturnRate(); if (returnRate <= returnRateConfig) { passTarget++; } //客诉率配置 Integer complaintRateConfig = expriConfiguration.getComplaintRate(); Integer complaintRate = expriData.getComplaintRate(); if (complaintRate <= complaintRateConfig) { passTarget++; } //损耗比率配置 Integer lossRateConfig = expriConfiguration.getLossRate(); Integer lossRate = expriData.getLossRate(); if (lossRate <= lossRateConfig) { passTarget++; } if (passTarget >= passTargetConfig) { return true; } return false; }
//考核不通过时,根据考核类型(试销期/滞销期)将考核指标数据,拆分填充到考核失败集合、考核中集合 //@param assessFailureList 考核不通过集合 //@param assessingList 考核中集合 //@param failTimesMap 连续失败次数数据Map,key是itemId //@param assessmentType 考核类型 //@param expriResult 考核指标数据 //@param expriConfiguration 考核指标配置 private void fillListByAssessmentType(List<ProductExpriDataResultDTO> assessFailureList, List<ProductExpriDataResultDTO> assessingList, Map<String, Integer> failTimesMap, Integer assessmentType, ProductExpriDataResultDTO expriResult, ProductExpriConfigurationDTO expriConfiguration) { //如果是试销考核 if (assessmentType.equals(AssessmentTypeEnum.TRY_SALE_ASSESS.getCode())) { //直接添加到考核不通过集合中 assessFailureList.add(expriResult); } //如果是滞销考核 if (assessmentType.equals(AssessmentTypeEnum.GROWN_SALE_ASSESS.getCode())) { //比较失败次数 Integer failTimes = failTimesMap.getOrDefault(expriResult.getItemId(), BigDecimal.ZERO.intValue()); Integer failTimesConfig = expriConfiguration.getFailTimes(); //如果小于配置的连续失败次数 if (++failTimes < failTimesConfig) { //添加到考核中集合 assessingList.add(expriResult); } else { //否则添加到考核不通过集合 assessFailureList.add(expriResult); } } } ...}
//考核结果资源管理@Repositorypublic class ItemExpriResultRepository { ... //分页查询出状态为考核中的考核缓冲结果数据中的连续失败次数集合 //@return 连续失败次数集合 public Map<String, Integer> listFailTimesByPage() { //构造查询条件 LambdaQueryWrapper<ItemExpriResultBufferDO> queryWrapper = Wrappers.lambdaQuery(); //考核状态为考核中 queryWrapper.eq(ItemExpriResultBufferDO::getMarketExpriResult, MarketExpriResultEnum.UNDER_EXAMINATION.getCode()); queryWrapper.eq(ItemExpriResultBufferDO::getDelFlag, YesOrNoEnum.YES.getCode());
//分页查询存放数据的总集合 Map<String, Integer> results = new HashMap<>();
int pageNum = 1; //设置每次查询的数据量,最大为200 int pageSize = ProductConstants.QUERY_ITEM_MAX_COUNT; Page<ItemExpriResultBufferDO> page = new Page<>(pageNum, pageSize); //查询第一页数据 Page<ItemExpriResultBufferDO> pageResult = itemExpriResultBufferMapper.selectPage(page, queryWrapper);
//判断是否还有数据,还有数据则页码+1继续执行分页查询 List<ItemExpriResultBufferDO> batchResult = pageResult.getRecords(); try { while (batchResult.size() >= ProductConstants.QUERY_ITEM_MAX_COUNT) { //将分页查询出来的list数据中的failTimes属性添加到Map集合中,itemId作为key putAll(results, batchResult); pageNum += 1; page.setCurrent(pageNum); page = itemExpriResultBufferMapper.selectPage(page, queryWrapper); batchResult = page.getRecords(); //每次循环获取数据后,休眠20ms,避免对数据库造成太大压力 Thread.sleep(20); } } catch (InterruptedException e) { throw new BaseBizException(ProductExceptionCode.PRODUCT_SQL); } //最后一组数据也放入结果集中 putAll(results, batchResult); return results; } ...}
复制代码


步骤七:商品考核数据分多种类别写入结果缓冲表


@Componentpublic class CalculateExpriResultSchedule {    ...    //批量将考核指标数据写入到考核结果缓冲表中    //@param itemIdList                 itemId集合    //@param assessFailureList          考核不通过的考核指标数据    //@param assessingList              考核中的考核指标数据    //@param totalExpriDataList         考核通过的考核指标数据    //@param nonAssessmentExpriDataList 免考核的考核指标数据    //@param itemPeriodStageMap         生命周期数据集合,key为itemId    private void batchInsertAssessmentResult(List<String> itemIdList, List<ProductExpriDataResultDTO> assessFailureList,             List<ProductExpriDataResultDTO> assessingList, List<ProductExpriDataResultDTO> totalExpriDataList,            List<ProductExpriDataResultDTO> nonAssessmentExpriDataList, Map<String, ItemPeriodStageDTO> itemPeriodStageMap) {        //1.分页查询考核缓冲表中考核状态是考核中的数据        Map<String, ItemExpriResultBufferDTO> itemExpriResultBufferMap = itemExpriResultRepository.listAssessingBufferResultByPage(itemIdList);
//2.批量写入考核不通过的考核指标数据 batchInsertByMarketExpriType(itemExpriResultBufferMap, assessFailureList, itemPeriodStageMap, MarketExpriResultEnum.FAIL_PASS_EXAMINATION.getCode(), BigDecimal.ONE.intValue(), BigDecimal.ONE.intValue()); //3.批量写入考核中的考核指标数据 batchInsertByMarketExpriType(itemExpriResultBufferMap, assessingList, itemPeriodStageMap, MarketExpriResultEnum.UNDER_EXAMINATION.getCode(), BigDecimal.ONE.intValue(), BigDecimal.ONE.intValue()); //4.批量写入考核通过的考核指标数据 batchInsertByMarketExpriType(itemExpriResultBufferMap, totalExpriDataList, itemPeriodStageMap, MarketExpriResultEnum.PASS_EXAMINATION.getCode(), BigDecimal.ZERO.intValue(), BigDecimal.ZERO.intValue()); //5.批量写入免考核指标数据 batchInsertByMarketExpriType(itemExpriResultBufferMap, nonAssessmentExpriDataList, itemPeriodStageMap, MarketExpriResultEnum.NON_EXAMINATION.getCode(), BigDecimal.ZERO.intValue(), BigDecimal.ZERO.intValue()); }
//根据考核状态批量将考核指标数据批量写入到考核结果缓冲表 //考核不通过: 新增操作默认连续失败次数为1,修改操作连续失败次数增加1 //考核中: 新增操作默认连续失败次数为1,修改操作连续失败次数增加1 //考核通过: 新增操作默认连续失败次数为0,修改操作连续失败次数增加0 //免考核: 新增操作默认连续失败次数为0,修改操作连续失败次数增加0 //@param itemExpriResultBufferMap 已存在的考核状态为考核中的考核结果缓冲数据,key为itemId //@param expriDataResultList 考核指标数据集合 //@param itemPeriodStageMap 生命周期数据,key为itemId //@param marketExpriResultType 考核状态:0:考核中;1:考核通过;2:考核不通过;3:不考核或暂停考核 //@param defaultFailTimes 新增考核缓冲结果数据时,默认的失败次数 //@param incrementFailTimes 修改考核缓冲结果数据时,增加的失败次数 private void batchInsertByMarketExpriType(Map<String, ItemExpriResultBufferDTO> itemExpriResultBufferMap, List<ProductExpriDataResultDTO> expriDataResultList, Map<String, ItemPeriodStageDTO> itemPeriodStageMap, Integer marketExpriResultType, Integer defaultFailTimes, Integer incrementFailTimes) { //需要插入考核结果缓冲表的集合数据 List<ItemExpriResultBufferRequest> insertRequest = new ArrayList<>(); for (ProductExpriDataResultDTO result : expriDataResultList) { String itemId = result.getItemId(); //如果考核结果缓冲表中不存在该记录 if (Objects.isNull(itemExpriResultBufferMap.get(itemId))) { //准备批量插入数据 ItemExpriResultBufferRequest request = new ItemExpriResultBufferRequest(); request.setItemId(itemId); request.setCategoryId(result.getCategoryId()); request.setPeriodStageId(itemPeriodStageMap.get(itemId).getProductPeriodId()); request.setFailTimes(defaultFailTimes); request.setMarketExpriResult(marketExpriResultType); request.setDelFlag(YesOrNoEnum.YES.getCode()); insertRequest.add(request); } else { //考核结果表中存在该记录,执行修改操作 ItemExpriResultBufferRequest request = new ItemExpriResultBufferRequest(); request.setItemId(itemId); Integer failTimes = itemExpriResultBufferMap.get(itemId).getFailTimes() + incrementFailTimes; request.setFailTimes(failTimes); request.setMarketExpriResult(marketExpriResultType); itemExpriResultRepository.updateItemExpriResultBuffer(request); } } //批量插入考核结果缓冲表 itemExpriResultRepository.insertBatch(insertRequest); } ...}
//考核结果资源管理@Repositorypublic class ItemExpriResultRepository { ... //分页查询考核缓冲表中考核状态是考核中的数据 //@param itemIdList itemId集合 //@return 考核数据Map,key为itemId public Map<String, ItemExpriResultBufferDTO> listAssessingBufferResultByPage(List<String> itemIdList) { if (CollectionUtils.isEmpty(itemIdList)) { return CollectionUtils.newHashMap(); } //考核中的考核结果缓冲数据集合 Map<String, ItemExpriResultBufferDTO> resultMap = new HashMap<>();
//一次最大查询200个数据,多个分页查询,这里做数据切割 List<List<String>> splitList = DataCuttingUtil.dataCuttingString(itemIdList, ProductConstants.QUERY_ITEM_MAX_COUNT); for (List<String> itemIds : splitList) { LambdaQueryWrapper<ItemExpriResultBufferDO> queryWrapper = Wrappers.lambdaQuery(); queryWrapper.in(ItemExpriResultBufferDO::getItemId, itemIds); queryWrapper.eq(ItemExpriResultBufferDO::getMarketExpriResult, MarketExpriResultEnum.UNDER_EXAMINATION.getCode()); queryWrapper.eq(ItemExpriResultBufferDO::getDelFlag, YesOrNoEnum.YES.getCode()); //分批次查询出符合条件的考核结果缓冲数据集合 List<ItemExpriResultBufferDO> assessingBufferResultList = itemExpriResultBufferMapper.selectList(queryWrapper); if (!CollectionUtils.isEmpty(assessingBufferResultList)) { Map<String, ItemExpriResultBufferDTO> result = assessingBufferResultList.stream() .map(itemExpriResultBufferDO -> itemExpriResultBufferConverter.entityToDTO(itemExpriResultBufferDO)) .collect(Collectors.toMap(ItemExpriResultBufferDTO::getItemId, itemExpriResultBuffer -> itemExpriResultBuffer, (oldKey, newKey) -> oldKey)); resultMap.putAll(result); } } return resultMap; }
//批量插入考核缓冲结果数据 public void insertBatch(List<ItemExpriResultBufferRequest> insertRequest) { List<ItemExpriResultBufferDO> bufferEntityList = itemExpriResultBufferConverter.listRequestToEntity(insertRequest); if (CollectionUtils.isEmpty(bufferEntityList)) { return; } Integer count = itemExpriResultBufferMapper.insertBatch(bufferEntityList); if (count <= 0) { throw new ProductBizException(CommonErrorCodeEnum.SQL_ERROR); } } ...}
复制代码


步骤八:将参与本轮考核计算的考核指标数据都设置为失效状态


@Componentpublic class CalculateExpriResultSchedule {    ...    //将参与本轮考核计算的考核指标数据都设置为失效状态    //@param itemIdList 本轮考核指标数据对应的itemId集合    private void batchInvalidExpriData(List<String> itemIdList) {        productExpriRepository.invalidExpriDataResult(itemIdList);    }    ...}
//商品考核资源管理@Repositorypublic class ProductExpriRepository { ... //将考核指标数据设置为失效状态 public Boolean invalidExpriDataResult(List<String> itemIdList) { if (CollectionUtils.isEmpty(itemIdList)) { return false; } LambdaUpdateWrapper<ProductExpriDataResultDO> updateWrapper = Wrappers.lambdaUpdate(); updateWrapper.in(ProductExpriDataResultDO::getItemId, itemIdList); updateWrapper.set(ProductExpriDataResultDO::getIsEffective, YesOrNoEnum.NO.getCode()); int count = productExpriDataResultMapper.update(null, updateWrapper); if (count <= 0) { throw new ProductBizException(CommonErrorCodeEnum.SQL_ERROR); } return true; } ...}
复制代码


(3)定时任务基于考核结果设置商品可采可补可售


步骤一:分页查每页1000条数据步骤二:判断是否考核通过,通过的放在passList,失败的放在failList步骤三:针对failList,设置供需状态,批量保存到考核结果表步骤四:针对passList,判断所处生命周期,拆分成滞销期list,试销期list步骤五:针对滞销期/试销期list,执行供需状态设置,保存到考核结果表步骤六:针对passList发送考核通过消息,针对failList发送考核失败消息步骤七:批量逻辑删除所有的考核通过/不通过的buffer数据
复制代码


@Componentpublic class CalculateExpriResultSchedule {    ...    //根据考核结果缓冲表中的考核状态和生命周期阶段,写入供需属性    @XxlJob("calculateExpri")    @Transactional(rollbackFor = Exception.class)    public void calculateExpri() {        //1.分页查,每页1000条数据        //2.批量判断是否考核通过,通过的放在passList,失败的放在failList        //3.针对failList的逻辑,执行对象转换,设置供需状态,批量保存到考核结果表        //4.针对passList的逻辑,执行对象转换,判断所处生命周期,拆分成滞销期list,试销期list        //5.针对滞销期/试销期list,执行供需状态设置,批量保存到考核结果表        //6.批量针对passList发送考核通过消息,针对failList发送考核失败消息        //7.批量逻辑删除所有的考核通过/不通过的buffer数据
//查询出考核结果数据 List<ItemExpriResultBufferDO> passExpriResultBufferList = getPassExpriResultBufferList(); List<ItemExpriResultBufferDO> failExpriResultBufferList = getFailExpriResultBufferList();
//批量处理考核成功结果 List<ItemExpriResultDO> passedHandledList = batchHandlePassExpriResults(passExpriResultBufferList);
//批量处理考核失败结果 List<ItemExpriResultDO> failedHandledList = batchHandleFailExpriResults(failExpriResultBufferList);
//批量分批次写入处理结果到考核表中 batchSaveExpriResult(passedHandledList); batchSaveExpriResult(failedHandledList);
//批量更新考核结果buffer数据为已失效 itemExpriResultRepository.batchDeleteExpriBuffer(passExpriResultBufferList); itemExpriResultRepository.batchDeleteExpriBuffer(failExpriResultBufferList); } ...}
复制代码


一.批量处理考核成功的结果


@Componentpublic class CalculateExpriResultSchedule {    ...    //查询考核通过的buffer数据list    private List<ItemExpriResultBufferDO> getPassExpriResultBufferList() {        List<ItemExpriResultBufferDO> passExpriResultBufferList = new ArrayList<>(ProductConstants.QUERY_ITEM_MAX_COUNT * 10);        Integer pageNum = 1;        try {            while (true) {                //分页查询考核结果缓冲数据                PageResult<ItemExpriResultBufferDO> page = itemExpriResultRepository.queryPassExpriResultBufferByPage(pageNum, ProductConstants.QUERY_ITEM_MAX_COUNT * 5);                //内容为空时,跳出循环                if (Objects.isNull(page) || CollectionUtils.isEmpty(page.getContent())) {                    break;                }                //查询到的结果集加入到通过list中                passExpriResultBufferList.addAll(page.getContent());                //页码+1                pageNum += 1;                Thread.sleep(20);            }        } catch (InterruptedException e) {            throw new BaseBizException("根据考核结果更新供需状态job,查询缓冲数据执行异常");        }        return passExpriResultBufferList;    }
//考核成功结果处理供需属性 private List<ItemExpriResultDO> batchHandlePassExpriResults(List<ItemExpriResultBufferDO> passExpriResultBufferList) { //批量处理考核成功结果 List<String> itemIds = new ArrayList<>(passExpriResultBufferList.size()); for (ItemExpriResultBufferDO resultBufferDO : passExpriResultBufferList) { //商品itemId String itemId = resultBufferDO.getItemId(); itemIds.add(itemId); } log.info("itemIds:{}", JSON.toJSONString(itemIds)); //分页处理考核通过结果 List<ItemPeriodStageDTO> stageDTOS = new ArrayList<>(passExpriResultBufferList.size()); Integer fromIndex = 0; while (true) { //如果起始大于了list的结束位置,就退出循环 if (fromIndex > passExpriResultBufferList.size() - 1) { break; } List<String> sbList = itemIds.subList(fromIndex, Math.min(fromIndex + ProductConstants.QUERY_ITEM_MAX_COUNT, passExpriResultBufferList.size())); //分批次更新商品前一次考核结果数据为失效 itemExpriResultRepository.batchDeleteExpriResult(sbList); //分批查询商品生命周期所处阶段 stageDTOS.addAll(itemPeriodStageRepository.queryPeriodStageByItemIds(new QueryPeriodListRequest(sbList))); fromIndex += ProductConstants.QUERY_ITEM_MAX_COUNT; } HashMap<String, Integer> itemStageMap = new HashMap(stageDTOS.size());
//转换成map结构,避免后续处理的时候,多次遍历stageDTOS list for (ItemPeriodStageDTO itemPeriodStageDTO : stageDTOS) { itemStageMap.put(itemPeriodStageDTO.getItemId(), itemPeriodStageDTO.getPeriodStage()); }
//循环设置考核结果供需属性 List<ItemExpriResultDO> handledPassResults = new ArrayList<>(passExpriResultBufferList.size()); for (ItemExpriResultBufferDO resultBufferDO : passExpriResultBufferList) { //生命周期阶段 Integer periodStage = itemStageMap.get(resultBufferDO.getItemId()); ItemExpriResultDO itemExpriResultDO = itemExpriResultConverter.converterBuffer(resultBufferDO); //试销期 if (periodStage.equals(ProductStageEnum.TRY_SALE.getCode())) { //设置对象初始值 itemExpriResultDO.setUpdateUser(1); itemExpriResultDO.initCommon(); //设置试销期供需状态 setTrySaleSupplyStatus(itemExpriResultDO); handledPassResults.add(itemExpriResultDO); } //成熟期 if (periodStage.equals(ProductStageEnum.GROWN.getCode())) { //设置对象初始值 itemExpriResultDO.setUpdateUser(1); itemExpriResultDO.initCommon(); //设置成熟期供需状态 setGrownSupplyStatus(itemExpriResultDO); handledPassResults.add(itemExpriResultDO); } } return handledPassResults; }
//设置试销期供需状态 private void setTrySaleSupplyStatus(ItemExpriResultDO itemExpriResultDO) { itemExpriResultDO.setPurchaseStatus(YesOrNoEnum.YES.getCode());//可采 itemExpriResultDO.setReplenishmentStatus(YesOrNoEnum.YES.getCode());//可补 itemExpriResultDO.setSaleStatus(YesOrNoEnum.YES.getCode());//可售 }
//设置成熟期供需状态 private void setGrownSupplyStatus(ItemExpriResultDO itemExpriResultDO) { String itemId = itemExpriResultDO.getItemId(); //商品状态 Integer itemStatus = itemPeriodStageRepository.getItemStatus(itemId); //处于上架状态 if (itemStatus.equals(ProductStatusEnum.PUT_ON_THE_MARKET.getCode())) { itemExpriResultDO.setPurchaseStatus(YesOrNoEnum.YES.getCode());//可采 itemExpriResultDO.setReplenishmentStatus(YesOrNoEnum.YES.getCode());//可补 itemExpriResultDO.setSaleStatus(YesOrNoEnum.YES.getCode());//可售 return; } //不处于上架状态 itemExpriResultDO.setPurchaseStatus(YesOrNoEnum.NO.getCode());//不可采 itemExpriResultDO.setReplenishmentStatus(YesOrNoEnum.NO.getCode());//不可补 itemExpriResultDO.setSaleStatus(YesOrNoEnum.NO.getCode());//不可售 } ...}
@Repositorypublic class ItemExpriResultRepository { ... //分页查询考核通过数据集 public PageResult<ItemExpriResultBufferDO> queryPassExpriResultBufferByPage(Integer pageNum, Integer pageSize) { LambdaQueryWrapper<ItemExpriResultBufferDO> queryWrapper = Wrappers.lambdaQuery(); queryWrapper.eq(ItemExpriResultBufferDO::getMarketExpriResult, MarketExpriResultEnum.PASS_EXAMINATION.getCode()); queryWrapper.eq(ItemExpriResultBufferDO::getDelFlag, YesOrNoEnum.YES.getCode()); Page<ItemExpriResultBufferDO> page = new Page<>(pageNum, pageSize); return new PageResult<>(itemExpriResultBufferMapper.selectPage(page, queryWrapper)); } ...}
复制代码


二.批量处理考核失败的结果


@Componentpublic class CalculateExpriResultSchedule {    ...    //查询考核失败的buffer数据list    private List<ItemExpriResultBufferDO> getFailExpriResultBufferList() {        List<ItemExpriResultBufferDO> passExpriResultBufferList = new ArrayList<>(ProductConstants.QUERY_ITEM_MAX_COUNT * 10);        Integer pageNum = 1;        try {            while (true) {                //分页查询考核结果缓冲数据                PageResult<ItemExpriResultBufferDO> page = itemExpriResultRepository.queryFailExpriResultBufferByPage(pageNum, ProductConstants.QUERY_ITEM_MAX_COUNT * 5);                //内容为空时,跳出循环                if (Objects.isNull(page) || CollectionUtils.isEmpty(page.getContent())) {                    break;                }                //查询到的结果集加入到通过list中                passExpriResultBufferList.addAll(page.getContent());                //页码+1                pageNum += 1;                Thread.sleep(20);            }        } catch (InterruptedException e) {            throw new BaseBizException("根据考核结果更新供需状态job,查询缓冲数据执行异常");        }        return passExpriResultBufferList;    }
//考核失败结果处理供需属性 private List<ItemExpriResultDO> batchHandleFailExpriResults(List<ItemExpriResultBufferDO> failExpriResultBufferList) { //考核结果数据集,考核缓冲数据处理转换成考核结果数据集合,并批量保存至数据库 List<ItemExpriResultDO> failExpriResultList = new ArrayList<>(failExpriResultBufferList.size()); List<String> itemIds = new ArrayList<>(failExpriResultBufferList.size()); //处理考核失败数据,设置淘汰期供需属性 for (ItemExpriResultBufferDO resultBufferDO : failExpriResultBufferList) { //克隆缓存对象属性到考核结果对象 ItemExpriResultDO itemExpriResultDO = itemExpriResultConverter.converterBuffer(resultBufferDO); itemExpriResultDO.setUpdateUser(1); itemExpriResultDO.initCommon(); //设置淘汰期供需状态 setPreEliminateSupplyStatus(itemExpriResultDO); failExpriResultList.add(itemExpriResultDO); //提取itemId itemIds.add(itemExpriResultDO.getItemId()); } Integer fromIndex = 0; while (true) { //如果起始大于了list的结束位置,就退出循环 if (fromIndex > failExpriResultBufferList.size() - 1) { break; } List<String> sbList = itemIds.subList(fromIndex, Math.min(fromIndex + ProductConstants.QUERY_ITEM_MAX_COUNT, failExpriResultBufferList.size())); //分批次更新商品前一次考核结果数据为失效 itemExpriResultRepository.batchDeleteExpriResult(sbList); fromIndex += ProductConstants.QUERY_ITEM_MAX_COUNT; } return failExpriResultList; }
//设置淘汰期供需状态 private void setPreEliminateSupplyStatus(ItemExpriResultDO itemExpriResultDO) { itemExpriResultDO.setPurchaseStatus(YesOrNoEnum.NO.getCode());//不可采 itemExpriResultDO.setReplenishmentStatus(YesOrNoEnum.NO.getCode());//不可补 itemExpriResultDO.setSaleStatus(YesOrNoEnum.YES.getCode());//可售 }
//批量保存处理过的考核结果数据到考核结果 private void batchSaveExpriResult(List<ItemExpriResultDO> handledList) { //分页写入考核失败结果至考核结果表 Integer fromIndex = 0; try { while (true) { //判断下一次的list拆分是否超过了 if (fromIndex > handledList.size() - 1) { break; } //每200条数据执行一次批量写 List<ItemExpriResultDO> subList = handledList.subList(fromIndex, Math.min(fromIndex + ProductConstants.QUERY_ITEM_MAX_COUNT, handledList.size())); itemExpriResultRepository.saveItemExpriResultBatch(subList); //设置下一页的起始位置 fromIndex += ProductConstants.QUERY_ITEM_MAX_COUNT; Thread.sleep(20); } } catch (InterruptedException e) { throw new BaseBizException("批量保存考核结果至考核结果表异常"); } } ...}
@Repositorypublic class ItemExpriResultRepository { ... //分页查询考核不通过数据集 public PageResult<ItemExpriResultBufferDO> queryFailExpriResultBufferByPage(Integer pageNum, Integer pageSize) { LambdaQueryWrapper<ItemExpriResultBufferDO> queryWrapper = Wrappers.lambdaQuery(); queryWrapper.eq(ItemExpriResultBufferDO::getMarketExpriResult, MarketExpriResultEnum.FAIL_PASS_EXAMINATION.getCode()); queryWrapper.eq(ItemExpriResultBufferDO::getDelFlag, YesOrNoEnum.YES.getCode()); Page<ItemExpriResultBufferDO> page = new Page<>(pageNum, pageSize); return new PageResult<>(itemExpriResultBufferMapper.selectPage(page, queryWrapper)); }
//批量写入到考核结果表中 public void saveItemExpriResultBatch(List<ItemExpriResultDO> list) { if (CollectionUtils.isEmpty(list)) { return; } int count = itemExpriResultMapper.saveBatch(list); if (count <= 0) { throw new BaseBizException(ProductExceptionCode.PRODUCT_SQL); } }
//批量设置考核结果buffer数据为失效状态 public void batchDeleteExpriBuffer(List<ItemExpriResultBufferDO> list) { if (CollectionUtils.isEmpty(list)) { return; } int count = itemExpriResultBufferMapper.batchDelete(list, YesOrNoEnum.NO.getCode()); if (count <= 0) { throw new BaseBizException(ProductExceptionCode.PRODUCT_SQL); } } ...}
复制代码


(4)考核结果数据的 Excel 导出


@RestController@RequestMapping("/ItemPeriodStage")public class ItemPeriodStageController {    @Autowired    private ItemPeriodStageService itemPeriodStageService;    ...
//导出数据到Excel @PostMapping("/exportItemExpriToExcel") public void exportExcel(@RequestBody ItemExpriReslutPageRequest request, HttpServletResponse response) throws IOException { try { List<ItemExpriResultToExcelDTO> itemExpriResults = itemPeriodStageService.queryItemExpriResultBatch(request); String title = "商品考核结果"; String sheetName = title; String fileName = title + System.currentTimeMillis(); log.info("result:{}", itemExpriResults); ExcelUtils.exportExcel(itemExpriResults, title, sheetName, ItemExpriResultToExcelDTO.class, fileName, response); } catch (BaseBizException baseBizException) { log.error("biz error: request={}", JSON.toJSONString(request), baseBizException); } catch (Exception e) { log.error("system error: request={}", JSON.toJSONString(request), e); } } ...}
@Servicepublic class ItemPeriodStageServiceImpl implements ItemPeriodStageService { ... //分页批量查询商品考核结果 @Override public List<ItemExpriResultToExcelDTO> queryItemExpriResultBatch(ItemExpriReslutPageRequest request) { //查询考核结果每次的数据量可能会比较大,所以预设一个较大的List初始大小,避免多次扩容 List<ItemExpriResultDTO> results = new ArrayList<>(ProductConstants.QUERY_ITEM_MAX_COUNT * 10); //1.设置每次查询的数据量,最大为200 request.setPageSize(ProductConstants.QUERY_ITEM_MAX_COUNT); Integer pageNum = request.getPageNum(); List<ItemExpriResultDTO> batchResult; try { while (true) { //2.分页数据 log.info("request:{}", JSON.toJSONString(request)); PageResult<ItemExpriResultDTO> page = itemPeriodStageRepository.queryItemExpriResultByPage(request); //3.判断是否还有数据,还有数据则页码+1继续执行分页查询 log.info("page:{}", JSON.toJSONString(page)); if (Objects.isNull(page) || CollectionUtils.isEmpty(page.getContent())) { break; } //4.拿到本次查询的数据 batchResult = page.getContent(); log.info("dataList:{}", JSON.toJSONString(batchResult)); //判断拿到的数据是否为空,或为null,若为空或为null,说明本次查询未查到数据,可直接break if (CollectionUtils.isEmpty(batchResult)) { break; } //6.查询到的数据全部加入到返回的结果集中,页码+1 results.addAll(batchResult); request.setPageNum(++pageNum); //每次循环获取数据后,休眠20ms,避免对数据库造成太大压力 Thread.sleep(20); } } catch (InterruptedException e) { throw new BaseBizException("查询出错,request:{}", JSON.toJSONString(request)); } log.info("result:{}", results); //7.返回转换后的结果集 return transferItemExpriResultToExcelDTO(results); } ...}
@Repositorypublic class ItemPeriodStageRepository { ... //根据分页查询考核结果 public PageResult<ItemExpriResultDTO> queryItemExpriResultByPage(ItemExpriReslutPageRequest request) { LambdaQueryWrapper<ItemExpriResultDO> queryWrapper = Wrappers.lambdaQuery(); queryWrapper.eq(ItemExpriResultDO::getDelFlag, YesOrNoEnum.YES.getCode()); //参数不为null,则设置为条件 if (!Objects.isNull(request.getCategoryId())) { queryWrapper.eq(ItemExpriResultDO::getCategoryId, request.getCategoryId()); } if (!Objects.isNull(request.getItemId())) { queryWrapper.eq(ItemExpriResultDO::getItemId, request.getItemId()); } Page<ItemExpriResultDO> page = new Page<>(request.getPageNum(), request.getPageSize()); Page<ItemExpriResultDO> skuPeriodStagePage = itemExpriResultMapper.selectPage(page, queryWrapper); return new PageResult<>(itemExpriResultConverter.converterDTOList(skuPeriodStagePage.getRecords())); } ...}
//Excel导入导出工具类public class ExcelUtils { ... //excel 导出 //@param list 数据列表 //@param title 表格内数据标题 //@param sheetName sheet名称 //@param pojoClass pojo类型 //@param fileName 导出时的excel名称 //@param response public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response) throws IOException { defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName, ExcelType.XSSF)); }
//excel 导出 //@param list 数据列表 //@param pojoClass pojo类型 //@param fileName 导出时的excel名称 //@param response //@param exportParams 导出参数(标题、sheet名称、是否创建表头,表格类型) private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) throws IOException { //把表头、表格数据添加到excel表格中 Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list); //下载Excel到本地 downLoadExcel(fileName, response, workbook); }
//excel下载 //@param fileName 下载时的文件名称 //@param response //@param workbook excel数据 private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) throws IOException { try { response.setCharacterEncoding("UTF-8"); response.setHeader("content-Type", "application/vnd.ms-excel"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "UTF-8")); workbook.write(response.getOutputStream()); } catch (Exception e) { throw new IOException(e.getMessage()); } } ...}
复制代码


文章转载自:东阳马生架构

原文链接:https://www.cnblogs.com/mjunz/p/18931935

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2025-04-01 加入

还未添加个人简介

评论

发布
暂无评论
商品中心—商品考核系统的技术文档(二)_架构_电子尖叫食人鱼_InfoQ写作社区