SpringBoot 实现 Excel 导入导出功能的三种实现方式
在日常开发中,Excel 的导入导出是非常常见的需求,尤其在管理系统中更是必不可少的功能。本文将基于实际项目代码,介绍三种不同的 Excel 导入导出实现方式,包括使用 EasyPOI 工具、自定义 POI 操作以及结合模板的 Excel 生成方式,并对它们的优缺点进行分析对比。
一、使用 EasyPOI 实现 Excel 操作
EasyPOI 是一款基于 POI 封装的 Excel 处理工具,它简化了 Excel 的导入导出代码,使开发更加高效。
1.1 导出功能实现
/*** 数据导出接口*/
@GetMapping("/exportExcel")
public Result exportExcel(PersonListQuery query) {// 1. 获取要导出的人员数据列表List<PersonListVO> personListvo = personService.exportExcel(query);// 2. 设置导出参数ExportParams exportParams = new ExportParams("人员数据报表","人员数据");exportParams.setStyle(ExcelExportStylerColorImpl.class);// 3. 生成Excel工作簿Workbook workbook = ExcelExportUtil.exportExcel(exportParams, PersonListVO.class, personListvo);String fileName = System.currentTimeMillis()+".xls";String filePath = Paths.get(excelPath, fileName).toString();// 4. 确保存储目录存在File file = new File(excelPath);if (!file.exists()) {file.mkdirs();}try{// 5. 写入文件ByteArrayOutputStream out = new ByteArrayOutputStream();workbook.write(out);byte[] excelBytes = out.toByteArray();Files.write(Paths.get(filePath), excelBytes);// 6. 关闭资源out.close();workbook.close();}catch (Exception e){e.printStackTrace();return Result.error("导出失败");}return Result.ok().put("data",fileName);
}
1.3 EasyPOI 方式优缺点
优点:
- 代码简洁,开发效率高
- 注解驱动,配置灵活
- 支持复杂表头、图片等复杂场景
- 自带样式美化功能
缺点:
- 额外引入第三方依赖
- 对于非常复杂的 Excel 模板支持不够灵活
二、基于 POI 的自定义 Excel 工具类
当需要更精细的控制 Excel 格式时,可以直接使用 Apache POI 进行自定义开发,封装成工具类使用。
public class ExcelUtil {public static String ExpPersonInfo(List<PersonVO> info, String path){POIFSFileSystem fs = null;int headRow = 2;// 数据起始行(跳过前2行表头)String descfile = null;try {// 1. 复制模板文件String srcfile = path + "personInfo.xls";// 源模板文件路径Date date = new Date();SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");String dateStr = format.format(date);descfile = dateStr + ".xls";FileInputStream fis = new FileInputStream(srcfile);FileOutputStream fos = new FileOutputStream(path+descfile);byte [] buffer = new byte[1024*4];while(fis.read(buffer) != -1){fos.write(buffer);}fis.close();fos.close();// 2. 打开新创建的文件并写入数据fs = new POIFSFileSystem(new FileInputStream(path + descfile));fos = new FileOutputStream(path + descfile);HSSFWorkbook wb1 = new HSSFWorkbook(fs);HSSFSheet sheet = wb1.getSheetAt(0);// 3. 创建单元格样式HSSFCellStyle style = wb1.createCellStyle();style.setBorderLeft(BorderStyle.THIN);style.setBorderRight(BorderStyle.THIN);style.setBorderTop(BorderStyle.THIN);style.setBorderBottom(BorderStyle.THIN);// 4. 写入数据int size = info.size();for(int i = 0;i < size;i++){int col = 0;PersonVO p = info.get(i);HSSFRow row = sheet.createRow(i+headRow);HSSFCell cell = row.createCell(col++);cell.setCellStyle(style);cell.setCellValue(p.getPersonId());cell = row.createCell(col++);cell.setCellStyle(style);cell.setCellValue(p.getCommunityName());// 其他列...}// 5. 保存并关闭wb1.write(fos);fos.close();} catch (Exception e) {e.printStackTrace();}return descfile;}
}
2.1 自定义工具类优缺点
优点:
- 完全自定义,灵活性高
- 可以精确控制 Excel 的每一个单元格
- 可以结合模板生成复杂格式的 Excel
缺点:
- 代码量大,开发效率低
- 需要手动处理样式、边框等细节
- 需注意资源关闭,否则可能导致内存泄漏
三、基于 POI 的通用导入实现
对于 Excel 导入,也可以直接使用 POI 实现通用的解析方案,适用于各种复杂结构的 Excel。
/*** 数据导入操作*/
@PostMapping("/parsefile/{fileName}")
public Result parsefile(@PathVariable("fileName") String fileName, HttpSession session){User user = (User) session.getAttribute("user");POIFSFileSystem fs = null;HSSFWorkbook wb = null;try {// 1. 读取Excel文件String basePath = excel + fileName;fs = new POIFSFileSystem(new FileInputStream(basePath));wb = new HSSFWorkbook(fs);} catch (Exception e) {e.printStackTrace();}// 2. 解析Excel内容到二维数组HSSFSheet sheet = wb.getSheetAt(0);Object[][] data = null;int r = sheet.getLastRowNum()+1;int c = sheet.getRow(0).getLastCellNum();int headRow = 2;data = new Object[r - headRow][c];for (int i = headRow; i < r; i++) {HSSFRow row = sheet.getRow(i);for (int j = 0; j < c; j++) {HSSFCell cell = null;try {cell = row.getCell(j);DataFormatter dataFormater = new DataFormatter();String a = dataFormater.formatCellValue(cell);data[i - headRow][j] = a;} catch (Exception e) {data[i-headRow][j] = "";// 特殊处理第一列if(j==0){try {double d = cell.getNumericCellValue();data[i - headRow][j] = (int)d + "";}catch(Exception ex){data[i-headRow][j] = "";}}}}}// 3. 处理解析后的数据并保存到数据库int row = data.length;String errinfo = "";headRow = 3;for (int i = 0; i < row; i++) {Person single = new Person();single.setPersonId(0);single.setState(1);single.setFaceUrl("");try {int col=1;String communityName = data[i][col++].toString();QueryWrapper<Community> queryWrapper = new QueryWrapper<>();queryWrapper.eq("community_name", communityName);Community community = this.communityService.getOne(queryWrapper);if( community == null){errinfo += "Excel文件第" + (i + headRow) + "行小区名称不存在!";return Result.ok().put("status", "fail").put("data", errinfo);}single.setCommunityId(community.getCommunityId());single.setTermName(data[i][col++].toString());single.setHouseNo(data[i][col++].toString());single.setUserName(data[i][col++].toString());// 设置其他字段...this.personService.save(single);} catch (Exception e) {e.printStackTrace();}}return Result.ok().put("status", "success").put("data","数据导入完成!");
}
3.1 通用 POI 导入优缺点
优点:
- 可以处理各种复杂格式的 Excel
- 对 Excel 结构的控制更加精细
- 适合导入格式不固定的场景
缺点:
- 代码复杂,需要处理各种异常情况
- 解析逻辑与业务逻辑混合,可读性差
- 开发和维护成本高
四、三种方式的对比与选择建议
实现方式 | 开发效率 | 灵活性 | 适用场景 | 依赖 |
---|---|---|---|---|
EasyPOI | 高 | 中 | 大部分常规导入导出场景 | 需引入 EasyPOI 依赖 |
自定义 POI 工具类 | 中 | 高 | 需要精确控制 Excel 格式,结合模板 | 仅需 POI 依赖 |
通用 POI 导入 | 低 | 高 | 复杂 Excel 结构,格式不固定 | 仅需 POI 依赖 |
选择建议:
- 对于大多数常规的 Excel 导入导出需求,优先选择 EasyPOI,开发效率最高
- 当需要使用模板生成复杂格式 Excel 时,可以采用自定义 POI 工具类的方式
- 当 Excel 格式复杂且不固定,或者有特殊解析需求时,才考虑使用通用 POI 导入方式
- 导入导出功能较多的项目,建议封装统一的工具类或服务,避免代码重复
五、文件上传通用处理
无论采用哪种导入方式,都需要先处理文件上传,以下是一个通用的文件上传实现:
@PostMapping("/excelUpload")
public Result excelUpload(@RequestParam("uploadExcel") MultipartFile file) throws Exception {if(file.getOriginalFilename().equals("")){return Result.error("没有选中要上传的文件");}else {// 生成唯一文件名String picName = UUID.randomUUID().toString();String oriName = file.getOriginalFilename();String extName = oriName.substring(oriName.lastIndexOf("."));String newFileName = picName + extName;// 保存文件File targetFile = new File(excel, newFileName);file.transferTo(targetFile);return Result.ok().put("data",newFileName);}
}
六、总结
Excel 导入导出是 Java 开发中的常见功能,选择合适的实现方式可以大大提高开发效率。EasyPOI 作为封装完善的工具,能够满足大部分需求;而当遇到复杂场景时,直接使用 POI 进行自定义开发则更加灵活。在实际项目中,应根据具体需求选择合适的实现方式,同时注意代码的可维护性和资源的正确释放。