起初頭兒讓我作一個excel的導出功能,由於以前作過,因此代碼比較簡單,可是因爲數據量龐大,致使導出的時間很長,因此只能改爲異步的方式。前端
話很少說,下面貼代碼吧。java
@RestController public class ExportExcelHelper { @Value("#{personConfig.defaultOrgTree}") private Integer defaultTreeId; @Autowired private CustomQueryService customQueryService; public static String RUNNING_STATUS = "該任務仍在運行中"; public static String STOP_STATUS = "該任務已經被手動中止"; public static String FINISH_STATUS = "該任務已經完成"; private volatile int runFlag = 0; //0無任務 1任務進行中 -1任務被手動中止 private Result<Progress> exportResult; XSSFWorkbook wb; String processid; /** * 用於將查詢出的數據寫入到excel的數據流中 * * @param queryTable 查詢出的數據 * @param totaltitle 第一行的總標題 * @return XSSFWorkbook excel數據流 * @author yuanyu * @since 2019.12.02 */ public static XSSFWorkbook exportExcel(QueryTable queryTable, String totaltitle) throws Exception { // 新建一個Excel文件 XSSFWorkbook wb = new XSSFWorkbook(); // Excel中的sheet XSSFSheet sheet = wb.createSheet(); //設置第一行也就是總標題的格式 XSSFCellStyle firstrowcellStyle = wb.createCellStyle(); firstrowcellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); Font totalTtileFont = wb.createFont(); totalTtileFont.setFontName("宋體"); totalTtileFont.setFontHeightInPoints((short) 18);//設置字體大小 totalTtileFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//粗體顯示 firstrowcellStyle.setFont(totalTtileFont); // 建立第一行 總標題行 XSSFRow firstrow = sheet.createRow(0); XSSFCell cell_00 = firstrow.createCell(0); cell_00.setCellValue(totaltitle); cell_00.setCellStyle(firstrowcellStyle); //建立第二行 屬性標題行 XSSFRow secondrow = sheet.createRow(1); XSSFCellStyle secondrowStyle = wb.createCellStyle(); secondrowStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); Font subtitleFont = wb.createFont(); //設置第二行屬性標題行的格式 subtitleFont.setFontName("宋體"); subtitleFont.setFontHeightInPoints((short) 12);//設置字體大小 subtitleFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//粗體顯示 secondrowStyle.setFont(subtitleFont); // 從參數queryTable中解析出打印的每列標題,放入title中 List<String> title = Lists.newArrayList(); for (QueryField p : queryTable.getHeader()) { title.add(p.getName()); } XSSFCell secondrowcell; // 給第一行賦值,值爲咱們從參數中解析出的標題,所以須要咱們在傳參的時候須要嚴格按照約定 for (int i = 0; i < title.size(); i++) { secondrowcell = secondrow.createCell(i); secondrowcell.setCellValue(title.get(i)); secondrowcell.setCellStyle(secondrowStyle); sheet.setColumnWidth(i, title.get(i).getBytes("UTF-8").length * 2 * 256); } //二重循環 將行和列的數據填充進去 XSSFCellStyle datarowStyle = wb.createCellStyle(); datarowStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); XSSFRow contextrow; XSSFCell datarowcell; for (int i = 1; i < queryTable.getRows().size(); i++) { contextrow = sheet.createRow(i + 1); for (int p = 0; p < queryTable.getHeader().size(); p++) { datarowcell = contextrow.createCell(p); datarowcell.setCellValue(queryTable.getRows().get(i).getString(queryTable.getHeader().get(p).getKey())); datarowcell.setCellStyle(datarowStyle); } } //將第一行標題進行合併 CellRangeAddress region = new CellRangeAddress(0, 0, 0, title.size() - 1); sheet.addMergedRegion(region); return wb; } private class Progress { private String start = DateUtils.parseDateToString(new Date()); private String end; private String status = RUNNING_STATUS; public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getStart() { return start; } public void setStart(String start) { this.start = start; } public String getEnd() { return end; } public void setEnd(String end) { this.end = end; } } private class Export extends Thread { CustomQueryVo query; Export(CustomQueryVo query) { this.query = query; } @Override public void run() { exportResult = Result.create(new Progress()); while (runFlag == 1) { //說明任務仍在進行中 query.setCatalogid(defaultTreeId); try { wb = excelExport(query).getResult(); break; } catch (Exception e) { if (e instanceof IErrorCode) { Result.create((IErrorCode) e); break; } else { Result.create(CommonError.internal_error); break; } } } if (exportResult.successful()) { exportResult.getResult().setEnd(DateUtils.parseDateToString(new Date())); if (runFlag == -1) { exportResult.getResult().setStatus(STOP_STATUS); } else { exportResult.getResult().setStatus(FINISH_STATUS); } } runFlag = 0; } } @PostMapping("/exportasyn") @ApiOperation("excel導出") @Api(value = "excel導出", permit = ApiPermit.LOGIN) public Result<Void> excelExportAsyn(@RequestBody CustomQueryVo query) throws Exception { query.setCatalogid(defaultTreeId); String namespace = query.getModel(); Integer catalogid = query.getCatalogid(); Integer nodeid = query.getNodeid(); if (catalogid == null || nodeid == null) { throw new MicroException(CommonError.illegal_args, "未設置查詢的組織目錄"); } List<QueryField> fields = query.getFields(); if (fields == null || fields.size() == 0) { throw new MicroException(CommonError.illegal_args, "未設置查詢的字段"); } if (!CustomQueryHelper.MODEL_USER.equals(query.getModel()) && !CustomQueryHelper.MODEL_ORG.equals(query.getModel())) { throw new MicroException(CommonError.illegal_args, "不支持" + namespace + "查詢"); } if (runFlag == 0) { runFlag = 1; Export export = new Export(query); export.start(); processid = UUIDUtils.generate(); System.out.println("線程id是"+processid); return Result.create(); } else { return Result.create(CommonError.illegal_operation, "excel正在導出請勿重複造做"); } } @GetMapping("/export/{id}") @ApiOperation("獲取進度") @Api(value = "獲取進度", permit = ApiPermit.LOGIN) public Result<Progress> progress(@PathVariable("id") String id ) { if (!id.equals(processid) || StringUtils.isEmpty(id)){ return Result.create(CommonError.notfound, "沒法找到該任務"); } if (exportResult == null) { return Result.create(CommonError.notfound, "暫無進度信息"); } return exportResult; } @GetMapping("/export/download") @ApiOperation("下載excel文件") @Api(value = "下載excel文件", permit = ApiPermit.LOGIN) public Result<Void> download(HttpServletResponse response) throws Exception { if (runFlag == 0) { Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String excelfilename = sdf.format(date) + ".xlsx"; response.setContentType("application/vnd.ms-excel;charset=UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + excelfilename); response.flushBuffer(); wb.write(response.getOutputStream()); wb.close(); return Result.create(); } else { return Result.create(CommonError.notfound, "沒法獲取數據"); } } @GetMapping("/export/stop") @ApiOperation("中止excel導出") @Api(value = "中止excel導出", permit = ApiPermit.LOGIN) public Result<Void> stop() { if (runFlag == 0) { return Result.create(CommonError.illegal_operation, "沒有任務"); } else { runFlag = -1; return Result.create(); } } /** * 根據條件查詢數據而且整理數據 * * @param query 前端傳來的查詢條件 * @return XSSFWorkbook excel數據流 * @author yuanyu * @since 2019/12/02 */ public Result<XSSFWorkbook> excelExport(CustomQueryVo query) throws Exception { String title = query.getTitle(); QueryTable queryTable = new QueryTable(); List<Data> dataList = new ArrayList<>(); query.setNeedtotal(false); int pagenumber = 1; query.setPagenum(pagenumber); query.setPagesize(2000); Result<QueryTable> queryTableResult; try { queryTableResult = customQueryService.query(query); } catch (Exception e) { if (e instanceof IErrorCode) { return Result.create((IErrorCode) e); } else { return Result.create(CommonError.internal_error); } } int maxheadernum = queryTableResult.getResult().getHeader().size(); long totalDataNumber = 0; Map<Integer, List<QueryField>> headermap = new HashMap<>(); while (queryTableResult.successful()) { totalDataNumber += queryTableResult.getResult().getRows().size(); if (totalDataNumber > 500000) { break; } System.out.println("查詢數據總數" + totalDataNumber); dataList.addAll(queryTableResult.getResult().getRows()); //獲取最大的屬性數 並將最大數與其對應的屬性集合放到map裏面 if (maxheadernum < queryTableResult.getResult().getHeader().size()) { maxheadernum = queryTableResult.getResult().getHeader().size(); } headermap.put(maxheadernum, queryTableResult.getResult().getHeader()); pagenumber++; query.setPagenum(pagenumber); try { queryTableResult = customQueryService.query(query); } catch (Exception e) { if (e instanceof IErrorCode) { return Result.create((IErrorCode) e); } else { return Result.create(CommonError.internal_error); } } } queryTable.setRows(dataList); queryTable.setHeader(headermap.get(maxheadernum)); XSSFWorkbook wb = ExportExcelHelper.exportExcel(queryTable, title); return Result.create(wb); } }