Web系統導出Excel是高頻需求。Apache POI雖強大但體積大、API複雜。JExcelApi (jxl.jar)輕量、API直觀、專注Excel讀寫,是中小項目導出功能的優選。本文演示從JavaBean到JSP的完整導出鏈路,並徹底解決中文亂碼與響應頭衝突問題。
下載jxl.jar(官網),放入WEB-INF/lib或Maven:
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.12</version>
</dependency>
package com.jagie.test;
import java.io.OutputStream;
import jxl.*;
import jxl.write.*;
import jxl.format.*;
import java.awt.Color;
public class ExcelExporter {
public static void writeExcel(OutputStream os) throws Exception {
WritableWorkbook wwb = Workbook.createWorkbook(os);
WritableSheet ws = wwb.createSheet("TestSheet1", 0);
// 普通單元格(中文無亂碼,JExcelApi內部UTF-16LE編碼)
Label labelC = new Label(0, 0, "我愛中國");
ws.addCell(labelC);
// 樣式單元格:字體、粗體、顏色、背景
WritableFont wfc = new WritableFont(WritableFont.ARIAL, 20, WritableFont.BOLD, false,
UnderlineStyle.NO_UNDERLINE, Colour.GREEN);
WritableCellFormat wcfFC = new WritableCellFormat(wfc);
wcfFC.setBackground(Colour.RED);
labelC = new Label(6, 0, "中國愛我", wcfFC);
ws.addCell(labelC);
wwb.write();
wwb.close(); // 必須close釋放資源
}
// 單元測試入口
public static void main(String[] args) throws Exception {
writeExcel(new java.io.FileOutputStream("test.xls"));
}
}
<%@ page import="com.jagie.test.ExcelExporter" %>
<%
// 1. 重置響應:清除容器可能預寫的內容(如JSP模板空白、錯誤頁片段)
response.reset();
// 2. 設置正確Content-Type:瀏覽器識別為Excel觸發下載/打開
response.setContentType("application/vnd.ms-excel");
// 建議添加Content-Disposition指定文件名
response.setHeader("Content-Disposition", "attachment; filename=export.xls");
// 3. 直接寫入Servlet輸出流
ExcelExporter.writeExcel(response.getOutputStream());
%>
response.reset()不可省略?JSP編譯後的Servlet會在_jspService開頭隱式寫入模板文本(換行、空白)。若不reset(),這些字節會混入Excel二進制流,導致文件損壞打不開。凡是二進制輸出(Excel/PDF/圖片/Zip),JSP頁面必須response.reset()開頭。
page指令contentType的誤區若在JSP頂部寫:
<%@ page contentType="application/vnd.ms-excel;charset=GBK" %>
容器生成的Servlet會先response.setContentType(...charset=GBK),隨後你的代碼response.reset()會清除該頭,但隨後out.print()模板文本時,容器可能再次隱式設置Content-Type,導致響應頭混亂。結論:二進制導出頁面,不要用page指令設置Content-Type,完全由代碼控制。
response.getOutputStream()前已有字符輸出(out.print())、或Content-Type缺失導致瀏覽器誤判編碼。response.setBufferSize(65536)、啟用response.setHeader("Content-Length", ...)(需預計算或分塊寫入臨時文件)。JExcelApi僅支持舊版.xls(BIFF8,65536行限制)。大數據量、.xlsx格式、流式寫入需遷移至POI SXSSFWorkbook(低內存流式):
SXSSFWorkbook wb = new SXSSFWorkbook(100); // 保留100行內存,其餘刷盤
Sheet sh = wb.createSheet();
Row row = sh.createRow(0);
row.createCell(0).setCellValue("大數據導出無壓力");
wb.write(response.getOutputStream());
wb.dispose(); // 釋放臨時文件
選對工具、控制響應頭、隔離模板輸出——三板斧搞定JSP導出Excel全場景。