maven依赖
<!-- 文件上传与下载-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
<!-- Apache POI(与 Hutool 兼容) -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
工具类
public class ExcelUtils {
public static void exportExcel(HttpServletResponse response,
List<?> dataList,
Class<?> clazz,
String fileName) throws IOException {
// 1. 获取字段名与表头映射(确保非空)
LinkedHashMap<String, String> headerMap = getApiModelPropertyNames(clazz);
if (headerMap.isEmpty()) {
throw new IllegalArgumentException("未找到有效的 @ApiModelProperty 注解字段");
}
// 2. 初始化 ExcelWriter
ExcelWriter writer = ExcelUtil.getWriter(true);
// 3. 设置字段别名(替代 writeHeader)
headerMap.forEach((fieldName, headerName) -> {
writer.addHeaderAlias(fieldName, headerName);
});
// 4. 写入数据(自动生成表头)
writer.write(dataList, true);
// 5. 设置响应头
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-Disposition", "attachment;filename=" + encodedFileName + ".xlsx");
// 6. 输出并关闭资源
writer.flush(response.getOutputStream(), true);
writer.close();
}
/**
* 安全获取字段映射(确保非空)
*/
private static LinkedHashMap<String, String> getApiModelPropertyNames(Class<?> clazz) {
LinkedHashMap<String, String> fieldMap = new LinkedHashMap<>();
Class<?> currentClass = clazz;
while (currentClass != null && currentClass != Object.class) {
for (Field field : currentClass.getDeclaredFields()) {
ApiModelProperty annotation = field.getAnnotation(ApiModelProperty.class);
if (annotation != null && !annotation.name().isEmpty()) {
fieldMap.put(field.getName(), annotation.name());
}
}
currentClass = currentClass.getSuperclass();
}
return fieldMap;
}
public static String[] getExclusions(Set<String> validFields) {
List<String> exclusions = new ArrayList<>();
Field[] allFields = ProjectInformation.class.getDeclaredFields();
for (Field field : allFields) {
if (!validFields.contains(field.getName())) {
exclusions.add(field.getName());
}
}
return exclusions.toArray(new String[0]);
}
}
controller层
@RequestMapping("/export.action")
public void export(HttpServletRequest request, HttpServletResponse response)throws IOException {
try {
// 初始化请求参数
Map<String, Object> requestMap = this.initRequestMap(request);
String year = StringUtil.trimStr(requestMap.get("year"));
String yzdw = StringUtil.trimStr(requestMap.get("yzdw"));
String name = StringUtil.trimStr(requestMap.get("value"));
// 查询数据
List<ProjectInformation> list = projectMsgMapper.selectReserveItems(year, yzdw);
if (list.isEmpty()) {
response.getWriter().write("无数据可导出");
return;
}
// 导出 Excel
String fileName = year + "年" + name + "集中立项申报表单";
ExcelUtils.exportExcel(response, list, ProjectInformation.class, fileName);
} catch (IOException e) {
e.printStackTrace();
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("导出失败: " + e.getMessage());
}
}