Apache POI 是 Java 操作 Microsoft Office 格式的事實標準庫。本文演示利用 POI HSSF(.xls 格式)將 MySQL 學生表數據導出為 Excel,含表頭樣式、中文支持、流式寫入與 Servlet 下載集成。
下載 POI 二進制包,僅需導入核心 JAR:
poi-3.17.jar(或更新版)poi-ooxml-3.17.jar(若需 .xlsx 支持)commons-codec-1.10.jar、commons-collections4-4.1.jar、commons-math3-3.6.1.jar(傳遞依賴)Maven 坐標:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
package org.xg.db;
public class DBConnection {
private static final String URL = "jdbc:mysql://localhost:3306/notebook";
private static final String DRIVER = "com.mysql.jdbc.Driver";
private static final String USER = "root";
private static final String PWD = "riskfitfeng";
private Connection con;
public DBConnection() {
try { Class.forName(DRIVER); con = DriverManager.getConnection(URL, USER, PWD); }
catch (Exception e) { e.printStackTrace(); }
}
public Connection getDB() { return con; }
public void close(ResultSet rs, PreparedStatement ps) {
closeQuietly(rs); closeQuietly(ps);
if (con != null) try { con.close(); } catch (SQLException ignore) {}
}
private void closeQuietly(AutoCloseable c) {
if (c != null) try { c.close(); } catch (Exception ignore) {}
}
}
package org.xg.db;
public class MySql2Excel {
public MySql2Excel() throws Exception {
Connection con = new DBConnection().getDB();
String sql = "select * from students";
ResultSet rs = con.createStatement().executeQuery(sql);
int colCount = rs.getMetaData().getColumnCount();
// 列標題
String[] headers = {"ID", "學號", "姓名", "性別", "班級"};
// 創建工作簿、工作表、表頭行
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("student表中的數據");
HSSFRow headerRow = sheet.createRow(0);
for (int i = 0; i < colCount; i++) {
HSSFCell cell = headerRow.createCell(i);
cell.setCellValue(new HSSFRichTextString(headers[i]));
// 可選:設置表頭樣式(粗體、背景色)
// CellStyle style = wb.createCellStyle(); ...
}
// 數據行
int rowIdx = 1;
while (rs.next()) {
HSSFRow row = sheet.createRow(rowIdx++);
for (int i = 0; i < colCount; i++) {
HSSFCell cell = row.createCell(i);
// 統一按字符串讀取,避免類型轉換異常
cell.setCellValue(new HSSFRichTextString(rs.getString(i + 1)));
}
}
// 寫入文件流
try (OutputStream out = new FileOutputStream("E:\\person.xls")) {
wb.write(out);
}
System.out.println("數據庫導出成功");
rs.close(); con.close();
}
public static void main(String[] args) {
try { new MySql2Excel(); } catch (Exception e) { e.printStackTrace(); }
}
}

@WebServlet("/exportExcel")
public class ExportExcelServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("application/vnd.ms-excel");
resp.setHeader("Content-Disposition", "attachment;filename=students.xls");
try (OutputStream out = resp.getOutputStream()) {
// 直接將 workbook.write(out) 寫入響應流,無需臨時文件
new MySql2Excel().exportToStream(out); // 將上述邏輯抽取為 exportToStream(OutputStream)
}
}
}
<a href="exportExcel" onclick="return confirm('確認導出到 Excel?');">導出數據到 Excel</a>
SXSSFWorkbook(流式 .xlsx),僅在內存保留滑動窗口行,避免 OOM。CellStyle、Font、DataFormat 為單例,按列類型應用(日期格式、數字千分位等)。rs.getMetaData().getColumnType(i) 分派 setCellValue(double/Date/Boolean/String),而非統一 getString。sheet.autoSizeColumn(i)(注意大數據量時性能)。