å®ç°çåè½ç¹
å¯¹äºæ¯ä¸ªæ¥è¡¨é½ç¸åçæä½ï¼æä»¬å¾èªç¶ç伿½ç¦»åºæ¥ï¼è¿ä¸ªå¾ç®åãèæéè¦çæ¯ï¼å¦ä½æé£äºæ¯ä¸ªæ¥è¡¨ä¸ç¸åçæä½è¿è¡è¯å¥½çå°è£ ï¼å°½å¯è½çæé«å¤ç¨æ§ï¼é对以ä¸çååï¼ä¸»è¦å®ç°äºä¸ä¸å ³é®åè½ç¹ï¼
- 导åºä»»æç±»åçæ°æ®
- èªç±è®¾ç½®è¡¨å¤´
- èªç±è®¾ç½®å段çå¯¼åºæ ¼å¼
使ç¨å®ä¾
ä¸é¢è¯´å°äºæ¬å·¥å ·ç±»å®ç°äºä¸ä¸ªåè½ç¹ï¼èªç¶å¨ä½¿ç¨çæ¶å设置好è¿ä¸ä¸ªè¦ç¹å³å¯ï¼
- è®¾ç½®æ°æ®å表
- 设置表头
- è®¾ç½®åæ®µæ ¼å¼
ä¸é¢çexport彿°å¯ä»¥ç´æ¥å客æ·ç«¯è¿åä¸ä¸ªexcelæ°æ®ï¼å ¶ä¸â
âproductInfoPosâ
âä¸ºå¾ å¯¼åºçæ°æ®å表ï¼â
âExcelHeaderInfoâ
âç¨æ¥ä¿å表头信æ¯ï¼å æ¬è¡¨å¤´åç§°ï¼è¡¨å¤´çé¦åï¼å°¾åï¼é¦è¡ï¼å°¾è¡ã
å 为é»è®¤å¯¼åºçæ°æ®æ ¼å¼é½æ¯å符串åï¼æä»¥è¿éè¦ä¸ä¸ªMapåæ°ç¨æ¥æå®æä¸ªåæ®µçæ ¼å¼åç±»åï¼ä¾å¦æ°åç±»åï¼å°æ°ç±»åãæ¥æç±»åï¼ãè¿é大家ç¥éä¸ªå¤§æ¦æä¹ä½¿ç¨å°±å¥½äºï¼ä¸é¢ä¼å¯¹è¿äºåæ°è¿è¡è¯¦ç»è§£é
代ç å®ç°â
1ãpom.xml
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<version>3.4.0</version>
</dependency>
<!-- poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
2ã导åºç±»
public class ExcelUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtils.class);
public static final int ROW_ACCESS_WINDOW_SIZE = 100;
public static final int SHEET_MAX_ROW = 100000;
private List list;
private List<ExcelHeaderInfo> excelHeaderInfos;
private Map<String, ExcelFormat> formatInfo;
public ExcelUtils(List list, List<ExcelHeaderInfo> excelHeaderInfos) {
this.list = list;
this.excelHeaderInfos = excelHeaderInfos;
}
public ExcelUtils(List list, List<ExcelHeaderInfo> excelHeaderInfos, Map<String, ExcelFormat> formatInfo) {
this.list = list;
this.excelHeaderInfos = excelHeaderInfos;
this.formatInfo = formatInfo;
}
public Workbook getWorkbook() {
Workbook workbook = new SXSSFWorkbook(ROW_ACCESS_WINDOW_SIZE);
String[][] datas = transformData();
Field[] fields = list.get(0).getClass().getDeclaredFields();
CellStyle style = setCellStyle(workbook);
int pageRowNum = 0;
Sheet sheet = null;
long startTime = System.currentTimeMillis();
LOGGER.info("å¼å§å¤çexcelæä»¶ããã");
for (int i = 0; i < datas.length; i++) {
// å¦ææ¯æ¯ä¸ªsheetçé¦è¡
if (i % SHEET_MAX_ROW == 0) {
// å建æ°çsheet
sheet = createSheet(workbook, i);
pageRowNum = 0; // è¡å·é置为0
for (int j = 0; j < getHeaderRowNum(excelHeaderInfos); j++) {
sheet.createRow(pageRowNum++);
}
createHeader(sheet, style);
}
// å建å
容
Row row = sheet.createRow(pageRowNum++);
createContent(row, style, datas, i, fields);
}
LOGGER.info("å¤çææ¬èæ¶" + (System.currentTimeMillis() - startTime) + "ms");
return workbook;
}
// å建表头
private void createHeader(Sheet sheet, CellStyle style) {
for (ExcelHeaderInfo excelHeaderInfo : excelHeaderInfos) {
Integer lastRow = excelHeaderInfo.getLastRow();
Integer firstRow = excelHeaderInfo.getFirstRow();
Integer lastCol = excelHeaderInfo.getLastCol();
Integer firstCol = excelHeaderInfo.getFirstCol();
// è¡è·æè
åè·å¤§äº0æè¿è¡åå
æ ¼èå
if ((lastRow - firstRow) != 0 || (lastCol - firstCol) != 0) {
sheet.addMergedRegion(new CellRangeAddress(firstRow, lastRow, firstCol, lastCol));
}
// è·åå½å表头çé¦è¡ä½ç½®
Row row = sheet.getRow(firstRow);
// å¨è¡¨å¤´çé¦è¡ä¸é¦åä½ç½®å建ä¸ä¸ªæ°çåå
æ ¼
Cell cell = row.createCell(firstCol);
// èµå¼åå
æ ¼
cell.setCellValue(excelHeaderInfo.getTitle());
cell.setCellStyle(style);
sheet.setColumnWidth(firstCol, sheet.getColumnWidth(firstCol) * 17 / 12);
}
}
// åå»ºæ£æ
private void createContent(Row row, CellStyle style, String[][] content, int i, Field[] fields) {
List<String> columnNames = getBeanProperty(fields);
for (int j = 0; j < columnNames.size(); j++) {
// å¦ææ ¼å¼åMap为空ï¼é»è®¤ä¸ºåç¬¦ä¸²æ ¼å¼
if (formatInfo == null) {
row.createCell(j).setCellValue(content[i][j]);
continue;
}
if (formatInfo.containsKey(columnNames.get(j))) {
switch (formatInfo.get(columnNames.get(j)).getValue()) {
case "DOUBLE":
row.createCell(j).setCellValue(Double.parseDouble(content[i][j]));
break;
case "INTEGER":
row.createCell(j).setCellValue(Integer.parseInt(content[i][j]));
break;
case "PERCENT":
style.setDataFormat(HSSFDataFormat.getBuiltinFormat("0.00%"));
Cell cell = row.createCell(j);
cell.setCellStyle(style);
cell.setCellValue(Double.parseDouble(content[i][j]));
break;
case "DATE":
style.setDataFormat(HSSFDataFormat.getBuiltinFormat("yyyy-MM-dd HH:mm:ss"));
Cell cell1 = row.createCell(j);
cell1.setCellStyle(style);
row.createCell(j).setCellValue(this.parseDate(content[i][j]));
}
} else {
row.createCell(j).setCellValue(content[i][j]);
}
}
}
// å°åå§æ°æ®è½¬æäºç»´æ°ç»
private String[][] transformData() {
int dataSize = this.list.size();
String[][] datas = new String[dataSize][];
// è·åæ¥è¡¨çåæ°
Field[] fields = list.get(0).getClass().getDeclaredFields();
// è·åå®ä½ç±»çåæ®µåç§°æ°ç»
List<String> columnNames = this.getBeanProperty(fields);
for (int i = 0; i < dataSize; i++) {
datas[i] = new String[fields.length];
for (int j = 0; j < fields.length; j++) {
try {
// èµå¼
datas[i][j] = BeanUtils.getProperty(list.get(i), columnNames.get(j));
} catch (Exception e) {
LOGGER.error("è·åå¯¹è±¡å±æ§å¼å¤±è´¥");
e.printStackTrace();
}
}
}
return datas;
}
// è·åå®ä½ç±»çåæ®µåç§°æ°ç»
private List<String> getBeanProperty(Field[] fields) {
List<String> columnNames = new ArrayList<>();
for (Field field : fields) {
String[] strings = field.toString().split("\\.");
String columnName = strings[strings.length - 1];
columnNames.add(columnName);
}
return columnNames;
}
// æ°å»ºè¡¨æ ¼
private static Sheet createSheet(Workbook workbook, int i) {
Integer sheetNum = i / SHEET_MAX_ROW;
workbook.createSheet("sheet" + sheetNum);
//卿æå®å½åçå·¥ä½è¡¨
return workbook.getSheetAt(sheetNum);
}
// è·åæ 颿»è¡æ°
private static Integer getHeaderRowNum(List<ExcelHeaderInfo> headerInfos) {
Integer maxRowNum = 0;
for (ExcelHeaderInfo excelHeaderInfo : headerInfos) {
Integer tmpRowNum = excelHeaderInfo.getLastRow();
if (tmpRowNum > maxRowNum) {
maxRowNum = tmpRowNum;
}
}
return maxRowNum + 1;
}
// 设置æ»ä½è¡¨æ ¼æ ·å¼
private static CellStyle setCellStyle(Workbook workbook) {
CellStyle style = workbook.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
style.setWrapText(true);
return style;
}
// åç¬¦ä¸²è½¬æ¥æ
private Date parseDate(String strDate) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = null;
try {
date = dateFormat.parse(strDate);
} catch (Exception e) {
LOGGER.error("åç¬¦ä¸²è½¬æ¥æé误");
e.printStackTrace();
}
return date;
}
// åéååºç»æ
public void sendHttpResponse(HttpServletResponse response, String fileName, Workbook workbook) {
try {
fileName += System.currentTimeMillis() + ".xlsx";
fileName = new String(fileName.getBytes(), "ISO8859-1");
response.setContentType("application/octet-stream;charset=ISO8859-1");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.addHeader("Pargam", "no-cache");
response.addHeader("Cache-Control", "no-cache");
OutputStream os = response.getOutputStream();
workbook.write(os);
os.flush();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3ãå®ä½ç±»å¯¹è±¡
3.1ExcelHeaderInfo
@Data
@AllArgsConstructor
@Accessors(chain = true)
public class ExcelHeaderInfo {
//æ é¢çé¦è¡åæ
private int firstRow;
//æ é¢çæ«è¡åæ
private int lastRow;
//æ é¢çé¦ååæ
private int firstCol;
//æ é¢çé¦è¡åæ
private int lastCol;
// æ é¢
private String title;
}
3.2ExcelFormat
public enum ExcelFormat {
FORMAT_INTEGER("INTEGER"),
FORMAT_DOUBLE("DOUBLE"),
FORMAT_PERCENT("PERCENT"),
FORMAT_DATE("DATE");
private String value;
ExcelFormat(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
4ãä¸å¡å±æ¹æ³
ExportService
public interface ExportService<T> {
List<T> list();
List<ExcelHeaderInfo> getHeaderInfo();
Map<String, ExcelFormat> getFormatInfo();
void export(HttpServletResponse response, String fileName);
}
ExportServiceImpl
public class ExportServiceImpl<T> implements ExportService<T> {
private static final Logger logger = LoggerFactory.getLogger(ExportServiceImpl.class);
@Override
public List<T> list() {
return null;
}
@Override
public List<ExcelHeaderInfo> getHeaderInfo() {
return null;
}
@Override
public Map<String, ExcelFormat> getFormatInfo() {
return null;
}
@Override
public void export(HttpServletResponse response, String fileName) {
// å¾
å¯¼åºæ°æ®
List<T> list = list();
ExcelUtils excelUtils = new ExcelUtils(list, getHeaderInfo(), getFormatInfo());
excelUtils.sendHttpResponse(response, fileName, excelUtils.getWorkbook());
}
}
çæ£è¦å¯¼åºçä¸å¡å±ï¼ç»§æ¿ä¸é¢çExportServiceImplï¼éåè·åæ°æ®çlistæ¹æ³åè·åè¡¨å¤´ãæ°æ®æ ¼å¼çæ¹æ³ã
TbTaskExportServiceImpl
@Service
public class TbTaskExportServiceImpl extends ExportServiceImpl<TbTask> {
@Autowired
private TbTaskMapper tbTaskMapper;
private static final int THREAD_MAX_ROW = 2000;
@Autowired
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Override
public List<TbTask> list() {
List<TbTask> result = new ArrayList<>();
List<Callable<List<TbTask>>> taskList = new ArrayList<>();
//è¡¨æ»æ°
Integer total = tbTaskMapper.selectCount(new QueryWrapper<>());
//æ ¹æ®è¡¨æ»æ°ç¡®å®æ¥è¯¢æ¬¡æ°
int selectNum = total / THREAD_MAX_ROW;
if (total % THREAD_MAX_ROW != 0) {
selectNum += 1;
}
for (int i = 0; i < selectNum; i++) {
//ç¨å¤çº¿ç¨æ¥è¯¢,å
å建callable
int num = THREAD_MAX_ROW;
int start = i + 1;
taskList.add(new TbTaskCallable(start, num));
}
long startTime = 0;
long endTime = 0;
try {
startTime = System.currentTimeMillis();
List<Future<List<TbTask>>> futureList = threadPoolTaskExecutor.getThreadPoolExecutor().invokeAll(taskList);
if (!CollectionUtils.isEmpty(futureList)) {
for (Future<List<TbTask>> data : futureList) {
result.addAll(data.get());
}
}
endTime = System.currentTimeMillis();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("=====æ¥è¯¢æ°æ®æ»æ¡æ°ï¼" + result.size());
System.out.println("=====å¤çº¿ç¨æ¥è¯¢èæ¶ï¼" + (endTime - startTime));
return result;
}
@Override
public List<ExcelHeaderInfo> getHeaderInfo() {
return Arrays.asList(
new ExcelHeaderInfo(0, 0, 0, 0, "taskId"),
new ExcelHeaderInfo(0, 0, 1, 1, "taskName"),
new ExcelHeaderInfo(0, 0, 2, 2, "taskDesc"),
new ExcelHeaderInfo(0, 0, 3, 3, "taskExp"),
new ExcelHeaderInfo(0, 0, 4, 4, "taskStatus"),
new ExcelHeaderInfo(0, 0, 5, 5, "taskClass"),
new ExcelHeaderInfo(0, 0, 6, 6, "updateTime"),
new ExcelHeaderInfo(0, 0, 7, 7, "createTime"),
new ExcelHeaderInfo(0, 0, 8, 8, "playId"),
new ExcelHeaderInfo(0, 0, 9, 9, "deviceId")
);
}
@Override
public Map<String, ExcelFormat> getFormatInfo() {
Map<String, ExcelFormat> format = new HashMap<>();
format.put("taskStatus", ExcelFormat.FORMAT_INTEGER);
format.put("updateTime", ExcelFormat.FORMAT_DATE);
format.put("createTime", ExcelFormat.FORMAT_DATE);
return format;
}
@Override
public void export(HttpServletResponse response, String fileName) {
super.export(response, fileName);
}
private class TbTaskCallable implements Callable<List<TbTask>> {
private int start;
private int num;
private List<TbTask> data;
public TbTaskCallable(int start, int num) {
this.start = start;
this.num = num;
}
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
@Override
public List<TbTask> call() throws Exception {
Page<TbTask> page = new Page<>(start, num);
IPage<TbTask> iPage = tbTaskMapper.selectPage(page, new QueryWrapper<>());
return iPage.getRecords();
}
}
}
5ãé 置类
5.1çº¿ç¨æ± é 置类ï¼ThreadPoolConfig
@Component
@Configuration
public class ThreadPoolConfig {
@Value("${threadpool.corePoolSize:5}")
private int corePoolSize;
/**
* çº¿ç¨æ± ç»´æ¤çº¿ç¨çæå¤§æ°é
* (max(tasks)- queueCapacity)/(1/taskcost)
*/
@Value("${threadpool.maxPoolSize:8}")
private int maxPoolSize;
/**
* ç¼åéå
* (coreSizePool/taskcost)*responsetime
*/
@Value("${threadpool.queueCapacity:30}")
private int queueCapacity;
/**
* å
许çç©ºé²æ¶é´
* é»è®¤ä¸º60
*/
@Value("${threadpool.keepAliveSeconds:100}")
private int keepAlive;
@Bean
public ThreadPoolTaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// è®¾ç½®æ ¸å¿çº¿ç¨æ°
executor.setCorePoolSize(corePoolSize);
// 设置æå¤§çº¿ç¨æ°
executor.setMaxPoolSize(maxPoolSize);
// 设置éå容é
executor.setQueueCapacity(queueCapacity);
// 设置å
许çç©ºé²æ¶é´ï¼ç§ï¼
executor.setKeepAliveSeconds(keepAlive);
// 设置é»è®¤çº¿ç¨åç§°
executor.setThreadNamePrefix("thread-taskExecutor-");
// 设置æç»çç¥rejection-policyï¼å½poolå·²ç»è¾¾å°max sizeçæ¶åï¼å¦ä½å¤çæ°ä»»å¡
// CALLER_RUNSï¼ä¸å¨æ°çº¿ç¨ä¸æ§è¡ä»»å¡ï¼èæ¯æè°ç¨è
æå¨ççº¿ç¨æ¥æ§è¡
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// çå¾
ææä»»å¡ç»æååå
³éçº¿ç¨æ±
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}
@MapperScan("com.hikvision.aradc.mapper")
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//åMybatisè¿æ»¤å¨é¾ä¸æ·»å åé¡µæ¦æªå¨
interceptor.addInnerInterceptor(new
PaginationInnerInterceptor(DbType.POSTGRE_SQL));
return interceptor;
}
}
ç»æï¼
æ§å¶å±å®ç°å¯¼åº
@GetMapping("/export")
public void export(HttpServletResponse response) {
TbTaskExportServiceImpl.export(response, "ååä¿¡æ¯" + new Random().nextInt(1000));
}