news 2026/8/26 15:48:15

java实现自定义注解导出excel

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
java实现自定义注解导出excel

结合Spring AOP (面向切面编程)Alibaba EasyExcel

EasyExcel 是阿里巴巴开源的工具,相比 Apache POI,它极其节省内存(基于流式读写),并且对注解支持非常好。


1. 引入依赖 (Maven)

pom.xml中引入 EasyExcel 和 Spring Boot AOP。

<dependencies><!-- Web 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- AOP 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!-- Alibaba EasyExcel (高性能 Excel 工具) --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</version><!-- 请检查最新版本 --></dependency><!-- Lombok (简化代码,可选) --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies>

2. 定义自定义注解@ResponseExcel

创建一个注解,用于标记 Controller 方法,告诉 AOP 这个接口需要导出 Excel。

packagecom.example.demo.annotation;importjava.lang.annotation.*;@Target(ElementType.METHOD)// 作用于方法@Retention(RetentionPolicy.RUNTIME)// 运行时有效@Documentedpublic@interfaceResponseExcel{// 导出的文件名StringfileName()default"data";// Sheet 名称StringsheetName()default"Sheet1";// 导出的实体类类型(用于解析表头)Class<?>clazz();}

3. 定义导出实体类 (Model)

使用 EasyExcel 提供的@ExcelProperty注解来定义表头。

packagecom.example.demo.model;importcom.alibaba.excel.annotation.ExcelIgnore;importcom.alibaba.excel.annotation.ExcelProperty;importcom.alibaba.excel.annotation.write.style.ColumnWidth;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importjava.util.Date;@Data@AllArgsConstructor@NoArgsConstructorpublicclassUserExcelVO{@ExcelProperty("用户ID")@ColumnWidth(20)privateLongid;@ExcelProperty("用户名")@ColumnWidth(30)privateStringusername;@ExcelProperty("年龄")privateIntegerage;@ExcelProperty("注册时间")@ColumnWidth(30)privateDatecreateTime;@ExcelIgnore// 忽略该字段,不导出privateStringpassword;}

4. 实现 AOP 切面处理逻辑 (核心)

这是整个功能的“大脑”。它拦截带有@ResponseExcel的方法,获取返回值(数据列表),然后直接写入 HttpServletResponse 流中。

packagecom.example.demo.aspect;importcom.alibaba.excel.EasyExcel;importcom.example.demo.annotation.ResponseExcel;importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.springframework.stereotype.Component;importorg.springframework.web.context.request.RequestContextHolder;importorg.springframework.web.context.request.ServletRequestAttributes;importjavax.servlet.http.HttpServletResponse;importjava.net.URLEncoder;importjava.util.List;@Aspect@ComponentpublicclassExcelExportAspect{/** * 环绕通知 * 拦截被 @ResponseExcel 注解的方法 */@Around("@annotation(responseExcel)")publicObjectaround(ProceedingJoinPointpoint,ResponseExcelresponseExcel)throwsThrowable{// 1. 执行目标方法,获取返回的数据列表Objectresult=point.proceed();// 如果返回的不是 List,或者为空,则直接返回原结果(或抛出异常,视业务而定)if(!(resultinstanceofList)){returnresult;}List<?>dataList=(List<?>)result;// 2. 获取 Response 对象ServletRequestAttributesrequestAttributes=(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();if(requestAttributes==null){returnnull;}HttpServletResponseresponse=requestAttributes.getResponse();if(response==null){returnnull;}// 3. 设置响应头信息response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// 防止中文乱码StringfileName=URLEncoder.encode(responseExcel.fileName(),"UTF-8").replaceAll("\\+","%20");response.setHeader("Content-Disposition","attachment;filename*=utf-8''"+fileName+".xlsx");// 4. 调用 EasyExcel 写入数据到流中try{EasyExcel.write(response.getOutputStream(),responseExcel.clazz()).sheet(responseExcel.sheetName()).doWrite(dataList);}catch(Exceptione){// 导出异常处理,比如重置 response 输出 JSON 错误信息response.reset();response.setContentType("application/json");response.setCharacterEncoding("utf-8");response.getWriter().println("{\"code\": 500, \"message\": \"导出Excel失败: "+e.getMessage()+"\"}");}// 5. 返回 null,因为数据已经写入 Response 流,不需要 Spring MVC 再处理返回值returnnull;}}

5. Controller 调用示例

现在,你只需要在 Controller 方法上加上@ResponseExcel即可实现导出,业务逻辑只需返回List

packagecom.example.demo.controller;importcom.example.demo.annotation.ResponseExcel;importcom.example.demo.model.UserExcelVO;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;importjava.util.ArrayList;importjava.util.Date;importjava.util.List;@RestController@RequestMapping("/excel")publicclassExcelController{/** * 导出用户列表 * 访问地址: http://localhost:8080/excel/export */@GetMapping("/export")@ResponseExcel(fileName="用户列表",sheetName="用户数据",clazz=UserExcelVO.class)publicList<UserExcelVO>exportUsers(){// 模拟查询数据库获取数据List<UserExcelVO>list=newArrayList<>();list.add(newUserExcelVO(1L,"张三",20,newDate(),"123"));list.add(newUserExcelVO(2L,"李四",25,newDate(),"456"));list.add(newUserExcelVO(3L,"王五",30,newDate(),"789"));// 直接返回 List 数据即可,AOP 会自动接管导出逻辑returnlist;}}

注意事项:

  1. 返回类型:被注解的方法必须返回List<T>类型的数据,否则 AOP 可能会抛错或忽略。
  2. JDK 8 兼容性:EasyExcel 和上述代码完全兼容 JDK 8。
  3. 文件名乱码:代码中使用了URLEncoder.encode(..., "UTF-8")并设置了filename*=utf-8'',这是标准的 HTTP 协议写法,能兼容绝大多数现代浏览器下载中文文件不乱码。
  4. 大数据量导出
    • 上面的代码是一次性把 List 加载到内存。如果你要导出 10 万行以上的数据,建议修改 Controller 和 AOP 逻辑,使其支持分页查询写入(doWrite可以多次调用),或者直接在 AOP 中接受Collection。EasyExcel 本身是流式的,只要你不把百万条数据一次性new出来放到 List 里,它就不会 OOM。
  5. 前端联调:前端调用此接口时,需要将responseType设置为blob,否则下载的文件可能是乱码字符串。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/26 11:17:02

基于Python的健身房管理系统源码设计与文档

前言在健身房精细化运营需求提升、传统管理模式存在 “会员管理混乱、课程预约低效、数据统计滞后、私教跟进缺位” 的痛点背景下&#xff0c;基于 Python 的健身房管理系统构建具有重要的商业与实用价值&#xff1a;从会员管理层面&#xff0c;系统依托 Python 的数据库交互能…

作者头像 李华
网站建设 2026/8/27 6:56:29

NVIDIA HGX™ B300 GPU Droplet 服务器,即将上线DigitalOcean 云平台!

人工智能正以史无前例的速度演进&#xff0c;新的模型和繁重的负载不断突破可能的边界。从复杂的大型语言模型&#xff08;LLM&#xff09;到精密的科学模拟&#xff0c;开发者与企业都需要获得最强大、最高效的算力基础设施。在 DigitalOcean&#xff0c;我们致力于提供顶级的…

作者头像 李华
网站建设 2026/8/27 9:40:24

基于SpringBoot旅游包车管理系统毕业设计项目源码

题目简介 在旅游包车行业存在 “供需对接碎片化、车辆调度效率低、行程监管缺失、费用结算不透明” 的行业痛点背景下&#xff0c;基于 SpringBoot 的旅游包车管理系统的构建具有重要现实意义与产业价值&#xff1a;从游客 / 旅行社端来看&#xff0c;系统打破传统线下找车、议…

作者头像 李华
网站建设 2026/8/26 19:47:43

硬件升级全攻略:从评估到优化

硬件升级前的准备工作评估当前硬件配置&#xff0c;包括处理器、内存、存储、显卡等关键部件的型号和性能。使用系统信息工具或第三方软件如CPU-Z、GPU-Z获取详细数据。明确升级目标和预算&#xff0c;确定是提升游戏性能、多任务处理能力还是存储速度。不同需求对应不同的硬件…

作者头像 李华
网站建设 2026/8/26 14:27:05

基于SpringBoot框架的个人博客系统毕业设计项目源码

题目简介在自媒体创作普及、个人内容表达需求日益增长的背景下&#xff0c;传统博客系统存在开发复杂度高、功能适配性差、内容管理低效、交互体验单一的痛点&#xff0c;难以满足创作者轻量化搭建、精细化运营个人内容平台的需求。基于 SpringBoot 框架的个人博客系统构建具有…

作者头像 李华
网站建设 2026/8/26 21:29:12

C++三大特性:封装、继承与多态深度解析

引言 C作为一门强大的面向对象编程语言&#xff0c;其核心的三大特性——封装、继承和多态&#xff0c;构成了面向对象编程的基石。 这三大特性不仅使代码更模块化、可重用&#xff0c;还大大提升了软件的可维护性和扩展性。本文将深入探讨这三大特性的技术细节、实现机制和最…

作者头像 李华