Java 生成 Excel 并提供下载
在 Java 中生成 Excel 文件并提供下载有多种方式,以下是几种常用的实现方法:

使用 Apache POI
Apache POI 是最常用的 Java 操作 Excel 的库。
Maven 依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
示例代码(Servlet 环境)
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
public class ExcelDownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. 创建工作簿
Workbook workbook = new XSSFWorkbook();
// 2. 创建工作表
Sheet sheet = workbook.createSheet("用户数据");
// 3. 创建标题行
Row headerRow = sheet.createRow(0);
headerRow.createCell(0).setCellValue("ID");
headerRow.createCell(1).setCellValue("姓名");
headerRow.createCell(2).setCellValue("年龄");
// 4. 添加数据行
Row dataRow1 = sheet.createRow(1);
dataRow1.createCell(0).setCellValue(1);
dataRow1.createCell(1).setCellValue("张三");
dataRow1.createCell(2).setCellValue(25);
Row dataRow2 = sheet.createRow(2);
dataRow2.createCell(0).setCellValue(2);
dataRow2.createCell(1).setCellValue("李四");
dataRow2.createCell(2).setCellValue(30);
// 5. 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=user_data.xlsx");
// 6. 写入输出流
try (OutputStream out = response.getOutputStream()) {
workbook.write(out);
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
使用 EasyExcel
EasyExcel 是阿里巴巴开源的 Excel 处理工具,性能更好,内存占用更小。
Maven 依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.1</version>
</dependency>
示例代码
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
public class EasyExcelDownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. 准备数据
List<UserData> dataList = new ArrayList<>();
dataList.add(new UserData(1, "张三", 25));
dataList.add(new UserData(2, "李四", 30));
// 2. 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=user_data.xlsx");
// 3. 写入Excel
try (OutputStream out = response.getOutputStream()) {
// 样式策略
WriteCellStyle headWriteCellStyle = new WriteCellStyle();
headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
WriteFont headWriteFont = new WriteFont();
headWriteFont.setFontHeightInPoints((short) 10);
headWriteCellStyle.setWriteFont(headWriteFont);
headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
HorizontalCellStyleStrategy horizontalCellStyleStrategy =
new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
EasyExcel.write(out, UserData.class)
.registerWriteHandler(horizontalCellStyleStrategy)
.sheet("用户数据")
.doWrite(dataList);
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
// 数据模型类
public static class UserData {
private Integer id;
private String name;
private Integer age;
// 构造方法、getter和setter省略...
}
}
使用 JXL
JXL 是一个较老的 Java Excel 库,但仍然简单易用。
Maven 依赖
<dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.12</version>
</dependency>
示例代码
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
public class JxlExcelDownloadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 1. 创建工作簿
try (OutputStream out = response.getOutputStream();
WritableWorkbook workbook = Workbook.createWorkbook(out)) {
// 2. 创建工作表
WritableSheet sheet = workbook.createSheet("用户数据", 0);
// 3. 添加标题
sheet.addCell(new Label(0, 0, "ID"));
sheet.addCell(new Label(1, 0, "姓名"));
sheet.addCell(new Label(2, 0, "年龄"));
// 4. 添加数据
sheet.addCell(new Label(0, 1, "1"));
sheet.addCell(new Label(1, 1, "张三"));
sheet.addCell(new Label(2, 1, "25"));
sheet.addCell(new Label(0, 2, "2"));
sheet.addCell(new Label(1, 2, "李四"));
sheet.addCell(new Label(2, 2, "30"));
// 5. 设置响应头
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=user_data.xls");
// 6. 写入工作簿
workbook.write();
out.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Spring Boot 环境下的实现
在 Spring Boot 中,可以使用 @RestController 和 ResponseEntity 来实现:

import com.alibaba.excel.EasyExcel;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@RestController
public class ExcelController {
@GetMapping("/download/excel")
public void downloadExcel(HttpServletResponse response) throws IOException {
// 准备数据
List<UserData> dataList = new ArrayList<>();
dataList.add(new UserData(1, "张三", 25));
dataList.add(new UserData(2, "李四", 30));
// 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition",
"attachment;filename=user_data.xlsx");
// 写入Excel
EasyExcel.write(response.getOutputStream(), UserData.class)
.sheet("用户数据")
.doWrite(dataList);
}
public static class UserData {
private Integer id;
private String name;
private Integer age;
// 构造方法、getter和setter省略...
}
}
注意事项
- 内存管理:对于大数据量,使用 EasyExcel 或 SXSSF (Apache POI 的大数据量处理方式) 避免内存溢出
- 文件名编码:中文文件名需要处理编码,可以使用
URLEncoder.encode()进行编码 - 异常处理:确保在 finally 块中关闭资源
- 响应头:正确设置 Content-Type 和 Content-Disposition 头
- 线程安全:在 Web 应用中确保 Excel 处理的线程安全
方法可以根据项目需求和技术栈选择合适的实现方式。

