亲爱的朋友们,热烈欢迎你们来到我的创意编程空间!能与你们在这里相聚,我感到无比激动和荣幸。在这个充满挑战与机遇的时代,我们每个人都在不断追求知识的深度与广度。而我的博客,正是一个激发灵感与分享智慧的乐园。在这里,你们不仅能够发现有趣的编程项目和实用的技术资源,还可以畅所欲言,分享你们的经验与想法。我真诚地期待着你们的到来,愿我们在这片小小的天地里携手前行,共同探索未知的领域。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
目录
引言
1、需求分析
1.1 核心需求
1.2 技术目标
2、设计与实现
2.1 核心设计思路
2.2 核心代码实现
2.2.1 定义注解
2.2.2 切面逻辑
2.2.3 测试示例
3、总结
在日常业务开发中,查询列表数据(如订单列表、购物车列表、待支付列表等)是一个非常常见的需求。而随着业务的发展,这些查询功能往往还需要支持数据导出(如导出为 Excel 文件)。传统的实现方式是为每个查询接口单独开发一个导出接口,导致大量重复代码和维护成本。为了解决这一问题,本文将介绍如何设计并实现一个 基于注解的通用列表导出组件,通过简单的配置即可为查询接口自动添加导出功能。
在查询方法上添加注解,支持动态导出功能。
通过请求参数标识是否执行导出操作。
导出的字段通过注解配置,支持灵活扩展。
导出文件名可通过参数动态指定。
减少重复代码,提升开发效率。
提供友好的 API 设计,降低使用成本。
注解驱动:通过自定义注解标记查询方法和导出字段。
AOP 拦截:利用 Spring AOP 拦截查询方法,根据请求参数动态切换导出逻辑。
反射解析字段:通过反射机制解析实体类中的导出字段注解,动态生成 Excel 列。
流式导出:使用 EasyExcel 实现高性能的流式导出,避免内存溢出。
// 标记查询方法支持导出
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExportExcel {
//导出的文件名
String fileName() default "导出列表.xlsx";
//前端传参的导出标识
String exportFlagParam() default "exportFlag";
}
// 标记导出字段
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExportField {
// 列名
String name();
// 列优先级顺序,值越小越优先
int order();
}
@Aspect
@Component
public class ExportAspect {
@Around("@annotation(exportExcel)")
public Object aroundExport(ProceedingJoinPoint joinPoint, ExportExcel exportExcel) throws Throwable {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();
// 判断是否触发导出
boolean isExport = Boolean.parseBoolean(request.getParameter(exportExcel.exportFlagParam()));
if (!isExport) {
// 正常执行查询
return joinPoint.proceed();
}
try {
// 执行原方法获取数据
JsonData> result = (JsonData)joinPoint.proceed();
if (ResultCodeEnum.SUCCESS.getCode().equals(result.getCode())){
List> dataList = (List>)result.getData();
// 生成Excel
String fileName = exportExcel.fileName();
ExcelUtil.exportExcel(dataList, fileName, response);
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
// 导出请求无需返回JSON
return null;
}
}
@ExportField注解中name为导出excel的列名,order为导出excel的列顺序,@ExportExcel注解中fileName 为需要导出的文件名称,exportFlagParam为指定前端确定是否导出的入参。
@Data
public class TestDemoDTO {
@ExportField(name = "姓名",order = 1)
private String name;
@ExportField(name = "年龄",order = 3)
private Integer age;
@ExportField(name = "性别",order = 2)
private String sex;
private String exportFlag;
}
@PostMapping(value = "/queryUserByName")
@ExportExcel(fileName = "导出Excel测试.xlsx",exportFlagParam = "export")
public JsonData> queryUserByName(String username,String export) {
// 模拟从数据库获取用户信息
List testDemoDTOs = new ArrayList<>();
for (int i = 0; i < 10; i++) {
TestDemoDTO testDemoDTO = new TestDemoDTO();;
testDemoDTO.setAge(15+i/3);
testDemoDTO.setName("张三"+i);
testDemoDTO.setSex(i%2 == 0 ? "男" : "女");
testDemoDTOs.add(testDemoDTO);
}
return JsonData.buildSuccess(testDemoDTOs);
}
测试示例中当传参export值为true时则为导出Excel
当传参export值为其他时则为查询列表
通过本文介绍的 基于注解的通用列表导出组件,我们可以显著减少重复代码,提升开发效率。该组件具有以下优势:
低侵入性:通过注解和 AOP 实现,无需修改业务逻辑。
高性能:基于 EasyExcel 的流式导出,支持大数据量场景。
灵活扩展:支持动态配置导出字段和文件名,满足多样化需求。
希望本文能为大家在实际开发中提供有价值的参考,助力高效开发!
了解idea插件的开发流程及idea右键选择项目批量导出插件介绍-CSDN博客
深入讲解TransmittableThreadLocal工作原理,并手写一个精简版的功能组件-CSDN博客
如何快速实现一个简单的通用缓存工具?-CSDN博客
java实现接口反参JsonData<T>封装,并实现字符串与泛型对象JsonData<T>之间的快速转换-CSDN博客