使用Reflect封装Excel导出工具类

本文使用的emoji: 💧 💦 ☔

最近遇到一个需求,需要对页面的列表数据做导出操作,考虑了很多实现方案之后,最终选择了hutool的ExcelWriter + Spring自带的Reflet包来实现这个功能,采用这种方式的主要原因是对现有代码改动较少,并且可以无缝切入系统,实现各个模块的导出操作,设计思路如下:

如上图所示,首先我们定义一个接口,此接口完成Excel导出功能,在ExcelExportService 中实现功能。

话不多说,上代码:

💧定义ExcelExportEnum

在导出Excel之前,我们需要先定义ExcelExportEnum,此枚举存储了我们后端需要导出的模块和模板名称


@Getter
@RequiredArgsConstructor
public enum ExcelExportEnum {

/**
 * 模块
 */
MODULE_A("moduleAService", "模块A");

private final String key;
private final String name;

}
复制代码

💧定义导出方法

💦校验入参

首先,我们需要对入参进行校验,查看传入的 MODULE_NAME 是否和后端Enum的一致,并且我们需要对参数中的自定义方法名进行提取,我们通过ExcelExportEnum来获取导出的module的Service名称

    if (!map.containsKey(MODULE_NAME)) {
        throw new BaseException("缺少参数:moduleName");
    }
    String moduleName = map.get(MODULE_NAME).toString();
    if (!EnumUtil.contains(ExcelExportEnum.class, moduleName)) {
        throw new BaseException("模块查找失败");
    }
    String functionName = DEFAULT_FUNCTION_NAME;
    //如果传了自定义方法名
    if (map.containsKey(CUSTOM_FUNCTION_NAME)) {
        functionName = map.get(CUSTOM_FUNCTION_NAME).toString();
    }
    String serviceName = ExcelExportEnum.valueOf(moduleName).getKey();
    String tableName = ExcelExportEnum.valueOf(moduleName).getName();
复制代码

💦利用java反射获取Service中的所有method

    Map<String, Method> methodMap = Arrays.stream(SpringContextHolder.getBean(serviceName).getClass().getMethods()).collect(Collectors.toMap(Method::getName, Function.identity(), (key1, key2) -> key2));
复制代码

在上述代码中SpringContextHolder.getBean(serviceName).getClass().getMethods()方法,首先通过getBean来获取 第一步中得到的ServiceName的Java bean。然后通过Class.getMethods()方法获取此service中的所有方法

最后,使用Arrays.stream方法,将module对应的Service中的所有method获取到,并放入methodMap中,供后续代码使用

💦提取method中的入参对象,获取其Class

    Object o;
    try {
        o = methodMap.get(functionName).getParameterTypes()[0].getDeclaredConstructor().newInstance();
    } catch (Exception e) {
        throw new BaseException(e);
    }
复制代码

通过Method.getParameterTypes()方法,将第二步中获取的method的入参的Class取到,并赋值给对象Object o,供后续调用分页列表接口传递入参匹配Class使用

💦传入参数,调用导出方法

    Map<String, Object> param = (Map<String, Object>) map.computeIfAbsent(PARAM, k -> new HashMap<String, Object>(4));
    param.put("limit", -1);
    CopyOptions copyOptions = new CopyOptions();
    copyOptions.setIgnoreError(true);
    PageUtils page = (PageUtils) methodMap.get(functionName).invoke(SpringContextHolder.getBean(serviceName), BeanUtil.mapToBean(param, o.getClass(), true, copyOptions));
    if (CollUtil.isEmpty(page.getList())) {
        throw new BaseException("数据获取失败");
    }
    Object resultObject = page.getList().get(0);
    ExcelUtils utils = new ExcelUtils(resultObject.getClass());
    utils.exportExcel(page.getList(), response, tableName, moduleName);
复制代码

可以看到,在上述导出方法中,我们使用了Method.invoke方法,并且设置转义忽略

💧注意事项

使用hutool工具包输出到流

// 通过工具类创建writer,默认创建xls格式 
ExcelWriter writer = ExcelUtil.getWriter(); 
//创建xlsx格式的 
//ExcelWriter writer = ExcelUtil.getWriter(true); 
// 一次性写出内容,使用默认样式,强制输出标题 
writer.write(rows, true); 
//out为OutputStream,需要写出到的目标流 
writer.flush(out); 
// 关闭writer,释放内存 
writer.close();
复制代码

注意 ExcelUtil.getWriter()默认创建xls格式的Excel,因此写出到客户端也需要自定义文件名为XXX.xls,否则会出现文件损坏的提示。 若想生成xlsx格式,请使用ExcelUtil.getWriter(true)创建。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的Excel导出工具类,可以将Java对象列表导出Excel文件。 ```java import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Field; import java.util.List; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.IndexedColors; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ExcelExporter { public static <T> void export(List<T> list, String[] headers, String[] fields, String filePath) throws IOException { Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Sheet1"); // Create header row Font headerFont = workbook.createFont(); headerFont.setBold(true); headerFont.setColor(IndexedColors.WHITE.getIndex()); CellStyle headerCellStyle = workbook.createCellStyle(); headerCellStyle.setFont(headerFont); headerCellStyle.setFillForegroundColor(IndexedColors.BLUE.getIndex()); headerCellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); Row headerRow = sheet.createRow(0); for (int i = 0; i < headers.length; i++) { Cell cell = headerRow.createCell(i); cell.setCellValue(headers[i]); cell.setCellStyle(headerCellStyle); } // Create data rows for (int i = 0; i < list.size(); i++) { T item = list.get(i); Row row = sheet.createRow(i + 1); for (int j = 0; j < fields.length; j++) { try { Field field = item.getClass().getDeclaredField(fields[j]); field.setAccessible(true); Object value = field.get(item); if (value != null) { Cell cell = row.createCell(j); if (value instanceof Number) { cell.setCellValue(((Number) value).doubleValue()); } else if (value instanceof String) { cell.setCellValue((String) value); } else { cell.setCellValue(value.toString()); } } } catch (NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); } } } // Auto size columns for (int i = 0; i < headers.length; i++) { sheet.autoSizeColumn(i); } // Write Excel file FileOutputStream outputStream = new FileOutputStream(filePath); workbook.write(outputStream); workbook.close(); outputStream.close(); } } ``` 使用工具类时,需要传入一个Java对象列表、一个字符串数组作为表头、一个字符串数组作为字段名,以及输出文件路径。该工具类会自动将Java对象列表转换为Excel文件,并写入到指定的输出文件中。 例如,如果有一个Student类,包含name、age和score三个字段,可以使用以下代码将Student列表导出Excel文件: ```java public class Student { private String name; private int age; private double score; // getters and setters } List<Student> list = new ArrayList<>(); list.add(new Student("Alice", 18, 90.0)); list.add(new Student("Bob", 20, 80.0)); list.add(new Student("Charlie", 22, 70.0)); ExcelExporter.export(list, new String[]{"Name", "Age", "Score"}, new String[]{"name", "age", "score"}, "students.xlsx"); ``` 该代码将会生成一个名为students.xlsx的Excel文件,包含三列数据:Name、Age和Score。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值