Java导出CSV文件(分页查询大数据量)

Java导出csv文件:

控制层:

@Controller
@RequestMapping("/historyReport/")
public class HistoryStockReportController {
    private static final Logger LOGGER = LoggerFactory.getLogger(HistoryStockReportController.class);

    @Autowired
    private HistoryStockReportService historyStockReportService;

 /**
     * 下载历史库存报表
     * @param request
     * @param response
     */
    @RequestMapping("new/downLoadHistoryStockInfo.htm")
    @ResponseBody
    public ResultMsg<Map<String, Object>> downLoadHistoryStockInfo(HttpServletRequest request,
            HttpServletResponse response) {
        String reportName = "PP视频_历史库存效果概况数据_" + DateUtils.getCurrentDateStr("yyyyMMddHHmmss");
        String[] header = Constant.PP_INDEX_DETAIL_HEAD_NAME_LIST;
        try {
            //点位/终端
            String pointLocation = request.getParameter(Constant.POINT_LOCATION_CODE);
            //广告位
            String positionScreenType = request.getParameter(Constant.POSITION_SCREEN_TYPE_CODE);
            String startDate = request.getParameter(Constant.START_DATE);
            String endDate = request.getParameter(Constant.END_DATE);
            //  判断接口参数
            if (!DateUtils.isDate(startDate) || !DateUtils.isDate(endDate)) {
                return ResultMsg.buildErrorMsg(Constant.DATE_ERROR_MSG);
            }
            //封装查询参数
            Map<String, Object> condition = new HashMap<>();
            condition.put(Constant.POINT_LOCATION_CODE, pointLocation);
            condition.put(Constant.POSITION_SCREEN_TYPE_CODE, positionScreenType);
            condition.put(Constant.START_DATE, startDate);
            condition.put(Constant.END_DATE, endDate);
            //导出csv
            exportBatch(response, condition, header, reportName);
        } catch (Exception e) {
            LOGGER.error("导出" + reportName + "发生错误:", e);
        }
        return null;
    }

/**
     * 导出报表
     * @param response
     * @param header
     * @param fileName
     * @throws IOException
     */
    private void exportBatch(HttpServletResponse response, Map<String, Object> condition, String[] header,
            String fileName) throws IOException {
        response.setContentType("application/vnd.ms-excel;charset=GBK");
        response.setHeader("Content-Disposition",
                "attachment;filename=" + new String((fileName).getBytes("GBK"), "ISO8859-1") + "." + "csv");
        StringBuilder sb = new StringBuilder();
        for (String s : header) {
            sb.append(s);
        }
        sb.append("\n");
        PrintWriter out = null;
        try {
            out = response.getWriter();
            out.print(sb.toString());
            int pageNumber = Constant.PAGE_NO;
            int pageSize = Constant.PAGE_SIZE;
            int dataLength = pageSize;
            while (dataLength == pageSize) {
                int startIndex = (pageNumber - 1) * pageSize;
                condition.put("startIndex", startIndex);
                condition.put("maxCount", pageSize);
                List<Map<String, Object>> resultList = historyStockReportService
                        .queryDownLoadHistoryStockInfo(condition);
                dataLength = resultList.size();
                String[] columns = Constant.PP_DETAIL_COLUMN.split(",");
                for (int i = 0; i < dataLength; i++) {
                    out.print(ExportUtils.handleExportData(resultList.get(i), columns));
                }
                out.flush();
                pageNumber++;
            }
        } catch (IOException e) {
            LOGGER.error("导出" + fileName + "发生错误:", e);
        } finally {
            if (out != null) {
                out.close();
            }
        }
    }
}

备注:这里查询list集合数据是按照分页查询,pageNo=1,pageSize=1000,这样支持大数据量导出,比如导出10万条数据,分页查询是为了防止把库查询挂了,数据量过大会发生导出OOM

业务层:

@Service
public class HistoryStockReportServiceImpl extends BaseImpl implements HistoryStockReportService {
    private static final Logger LOGGER = LoggerFactory.getLogger(HistoryStockReportServiceImpl.class);
    //定义数据库查询字段
    private String[] columnArray = Constant.CHECK_PP_INDEX_COLUMN.split(",");
    @Autowired
    private DalClient dalClient;

/**
     * 下载历史库存报表
     * @param condition
     * @return
     */
    public List<Map<String, Object>> queryDownLoadHistoryStockInfo(Map<String, Object> condition) {
        List<Map<String, Object>> resultList = dalClient
                .queryForList("historyStockData.queryDownLoadHistoryStockInfo", condition);
        if (!CollectionUtil.isEmptyList(resultList)) {
            IndexDataFormatUtils.coverPpInfo(resultList, columnArray);
        }
        return resultList;
    }
}

查询集合处理工具类:IndexDataFormatUtils

public class IndexDataFormatUtils {
    
    /**
     * 统一处理PP视频历史库存、特殊渠道指标报表的衍生指标数据
     * @param list
     * @param columnArray
     */
    public static void coverPpInfo(List<Map<String, Object>> list, String[] columnArray) {
        for (Map<String, Object> map : list) {
            //  组装处理rate参数
            calculateRate(map, Constant.FEE_PRACTICAL_SHOW_NUM, Constant.THEORY_STOCK_NUM, Constant.FILLFEE_RATE);
            calculateRate(map, Constant.DELIVERY_PRACTICAL_SHOW_NUM, Constant.THEORY_STOCK_NUM,
                    Constant.DELIVERY_FILL_RATE);
            calculateRate(map, Constant.SHOW_NUM, Constant.THEORY_STOCK_NUM, Constant.THEORY_STOCK_RATE);
            calculateRate(map, Constant.THEORY_STOCK_REMAINED_NUM, Constant.THEORY_STOCK_NUM,
                    Constant.THEORY_STOCK_REMAINED_RATE);
            //  处理数据值为null的单一指标
            coverIndexInfoFromNull(map, columnArray);
        }
    }


     /**
     * 处理占比参数
     *
     * @param map
     * @param dividendKey
     * @param divisorKey
     * @param quotientKey
     */
    public static void calculateRate(Map<String, Object> map, String dividendKey, String divisorKey, String quotientKey) {
        if (StringUtils.isBlank(MapUtils.getString(map,dividendKey)) || StringUtils.isBlank(MapUtils.getString(map,divisorKey))) {
            map.put(quotientKey,"-");
            return;
        }
        BigDecimal dividend = BigDecimal.valueOf(MapUtils.getDoubleValue(map, dividendKey));    //  被除数
        BigDecimal divisor = BigDecimal.valueOf(MapUtils.getDoubleValue(map, divisorKey));      //  除数
        BigDecimal quotient = BigDecimal.valueOf(0.00);
        //  =0 相等  >0前者大于后者 ,反之 <0 前者小于后者
        if(dividend.compareTo(BigDecimal.ZERO) != 0 && divisor.compareTo(BigDecimal.ZERO) != 0){
            quotient = dividend.multiply(BigDecimal.valueOf(100)).divide(divisor,2,BigDecimal.ROUND_HALF_UP);
        }
        map.put(quotientKey, quotient.setScale(2) + "");
    }

    /**
     * 处理数据值为null的单一指标
     * @param map
     * @param columnArray
     */
    public static void coverIndexInfoFromNull(Map<String, Object> map, String[] columnArray) {
        for (String columnName : columnArray) {
            String columnValue = MapUtils.getString(map,columnName);
            if (StringUtils.isBlank(columnValue)) {
                map.put(columnName,"-");
            }else {
                map.put(columnName,columnValue);
            }
        }
    }


}

导出数据处理工具类:ExportUtils

public class ExportUtils {
    
    /**
     * 处理下载指标
     *
     */
    public static String handleExportData(Map<String,Object> reportData, String[] columns){
        StringBuilder sb = new StringBuilder();
        for (String columnName:columns) {
            addStringBuffer(sb,reportData,columnName);
        }
        sb.append("\n");
        return  sb.toString();
    }

    public static void addStringBuffer(StringBuilder sb, Map<String, Object> map,String name){
        if(map.get(name) == null ){
            sb.append("-,");
        }else{
            String value = String.valueOf(map.get(name));
            String temp = value.replaceAll("\r", "").replaceAll("\n", "");
            if(temp.contains(",")){
                if(temp.contains("\"")){
                    temp=temp.replace("\"", "\"\"");
                }
                //将逗号转义
                temp="\""+temp+"\"";
            }
            sb.append("\t").append(temp).append(",");
        }
    }

}
常量类:
//导出默认分页
public static final int PAGE_NO = 1;
public static final int PAGE_SIZE = 1000;

 /**
  * PP视频
  * 历史存储、特殊渠道数据库查询字段
  */
public static final String CHECK_PP_INDEX_COLUMN =
            "requestNum,advertiserVvNum,responseNum,showNum,clickNum,theoryStockNum,fillFeeNum,"
                    + "feePracticalShowNum,deliveryFillNum,deliveryPracticalShowNum,theoryStockRemainedNum,"
                    + "systemExceptionLost,userExitLost,income";


 /**
     * 20190509
     * pp视频历史库存、特殊渠道日志数据报表
     * 报表下载模板头部(英文)
     */
    public static final String PP_DETAIL_COLUMN = "countDate,pointLocationCode,pointLocationName,positionScreenTypeCode,positionScreenTypeName," +
            "requestNum,advertiserVvNum,responseNum,showNum,clickNum,theoryStockNum,fillFeeNum,feePracticalShowNum,deliveryFillNum," +
            "deliveryPracticalShowNum,theoryStockRemainedNum,systemExceptionLost,userExitLost,income,fillFeeRate,deliveryFillRate," +
            "theoryStockRate,theoryStockRemainedRate";

/**
  * pp视频历史库存日志数据报表
  * 报表下载模板头部(中文)
 */
public static final String[] PP_INDEX_DETAIL_HEAD_NAME_LIST = {"统计时间,","点位/终端编码,","点位/终端名称,","广告位编码,", "广告位名称,",
            "请求量,", "广告vv量,","返回量,","曝光量,", "点击量,", "理论库存量,", "付费填充量,", "付费实际曝光量,", "配送填充量,",
            "配送实际曝光量,", "理论库存余量,", "系统异常损失,", "用户退出损失,","收入,", "付费使用率,", "配送使用率,", "库存使用率,",
            "库存余量占比,"};

导出效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值