首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring MVC + POI 實現 Excel 導入數據庫完整實戰:從前端上傳到異常處理

     編輯:Java 相關知識

業務場景

批量導入業務數據(如樣本信息、患者資料),前端上傳 .xls/.xlsx 文件,後端解析入庫,支持多 Sheet、多數據類型(字符串、數字、日期、布爾)。

架構分層

  • Controller:接收 MultipartFile、調用 Service、返回結果
  • Service:POI 解析 Excel、數據轉換、調用 DAO 入庫
  • DAO:Hibernate Session 操作

關鍵配置

1. Spring 文件上傳解析器

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

2. 前端表單(關鍵屬性)

<form enctype="multipart/form-data" method="post" action="${ctx}/uploadfile">
  <input type="file" name="file" />
  <input type="submit" value="提交" />
</form>

避坑:action 勿用 upload 作為路徑,極易與框架內部映射衝突導致 404(作者踩坑一天)。

Service 核心:POI 通用解析邏輯

@Service
public class FileUploadServiceImpl implements IFileUploadService {
    @Autowired private IFileUploadDao fileDao;

    @Override
    public List<String[]> readExcel(String path) {
        List<String[]> data = new ArrayList<>();
        try (FileInputStream fis = new FileInputStream(path)) {
            Workbook wb = WorkbookFactory.create(fis); // 自動識別 2003/2007+
            for (int s = 0; s < wb.getNumberOfSheets(); s++) {
                Sheet sheet = wb.getSheetAt(s);
                for (Row row : sheet) {
                    if (row.getRowNum() == 0) continue; // 跳過表頭
                    int cellCount = row.getPhysicalNumberOfCells();
                    String[] rowData = new String[cellCount - 1]; // 第一列為 ID 標識,不入庫
                    for (int c = 1; c < cellCount; c++) {
                        Cell cell = row.getCell(c);
                        rowData[c - 1] = getCellValueAsString(cell); // 統一轉字符串
                    }
                    data.add(rowData);
                }
            }
        } catch (Exception e) { throw new RuntimeException("Excel 解析失敗", e); }
        return data;
    }

    private String getCellValueAsString(Cell cell) {
        if (cell == null) return "";
        switch (cell.getCellTypeEnum()) {
            case STRING: return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell))
                    return new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
                return String.valueOf(cell.getNumericCellValue());
            case BOOLEAN: return String.valueOf(cell.getBooleanCellValue());
            case BLANK: return "";
            case FORMULA: return "FORMULA";
            case ERROR: return "ERROR";
            default: return "UNKNOWN";
        }
    }

    @Override public void save(Object o) { fileDao.save(o); }
}

Controller 入庫邏輯

@RequestMapping("/uploadfile")
public String upload(@RequestParam("file") MultipartFile file, HttpServletRequest request, ModelMap model) {
    String realPath = request.getServletContext().getRealPath("upload");
    File target = new File(realPath, file.getOriginalFilename());
    target.getParentFile().mkdirs();
    file.transferTo(target);

    List<String[]> rows = fileUploadService.readExcel(target.getAbsolutePath());
    SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
    for (String[] cols : rows) {
        Sample sample = new Sample(
            cols[0],                    // sampleNo
            Integer.parseInt(cols[1]),  // sampleType
            fmt.parse(cols[2]),         // createTime
            cols[3],                    // name
            cols[4]                     // pId
        );
        Patient patient = new Patient(cols[5], cols[6]); // hospitalName, cellPhone
        fileUploadService.save(sample);
        fileUploadService.save(patient);
    }
    return "redirect:/yyd";
}

生產級優化建議

  1. 大文件流式解析:使用 SXSSFWorkbook (POI 3.8+) 或 EasyExcel (Alibaba) 避免 OOM。
  2. 事務批量提交:每 500-1000 條 session.flush() + session.clear(),防止一級緩存撐爆內存。
  3. 數據校驗與錯誤回收:解析階段收集錯誤行,生成錯誤報告 Excel 返回前端,而非直接拋異常中斷。
  4. 異步處理:大文件導入改為異步任務(消息隊列 + 線程池),前端輪詢進度。
  5. 模板下載:提供標準模板 .xlsx 下載,減少用戶填寫錯誤。

總結

Spring MVC + POI 實現 Excel 導入核心在於:MultipartFile 接收 → WorkbookFactory 通用解析 → 統一轉字符串 → 批量入庫。掌握通用解析邏輯與生產級優化點,即可應對絕大多數批量導入場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved