【纯干货】SSM 实现将数据导出为 Excel 表格(利用反射实现类型通配) 您所在的位置:网站首页 ssm导出excel表格自动合并换行 【纯干货】SSM 实现将数据导出为 Excel 表格(利用反射实现类型通配)

【纯干货】SSM 实现将数据导出为 Excel 表格(利用反射实现类型通配)

2024-05-23 21:33| 来源: 网络整理| 查看: 265

0. 这里假设 SSM 环境已经搭建完成 1. 需要三个依赖包 org.apache.poi poi-ooxml 5.0.0 org.apache.poi poi 5.0.0 com.alibaba easyexcel 2.2.10 2. 核心工具类

目标是传入泛型数据列表 List dataList 实现将所有类型输出为 excel 表格,而不需要自己手动指定属性,所以对类的操作必不可少

这里利用反射达到了类的成员变量名 以及得到成员变量名和其值的映射关系(使用 Map,键是成员变量名 String ,值是成员变量值 Object)

ClassUtils.java

package com.iceclean.utils; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author : Ice'Clean * @date : 2021-08-05 * * 对类的操作 */ public class ClassUtils { /** * 通过类型返回对应的属性列表 * @param target 目标类型 * @return 属性列表 */ public static List getFields(Class target) { // 获取所有成员变量名称 List fieldList = new ArrayList(); Field[] declaredFields = target.getDeclaredFields(); // 放入 List 集合中 for(Field field : declaredFields) { fieldList.add(field.getName()); } return fieldList; } /** * 获取泛型所有的成员及其值的映射 * @param data 泛型对象 * @param 泛型 * @return 成员变量名和成员变量值的映射 */ public static Map getFieldOfValue(T data) throws IllegalAccessException { // 获取所有成员变量,并建立一个 Map(大小为成员变量的个数)来存放名字和值的对应关系 Field[] declaredFields = data.getClass().getDeclaredFields(); Map fieldMap = new HashMap(declaredFields.length); // 获取每个成员属性对应的值,并映射 for (Field field : declaredFields) { // 允许访问私有变量的值 field.setAccessible(true); // 获取成员变量的值,并放入 map 中 fieldMap.put(field.getName(), field.get(data)); } return fieldMap; } } 3. 核心代码 /** * 将列表数据导出为 Excel 表格 * @param dataList 列表数据 * @param out 输出源 * @param 数据的类型 */ public static void exportExcel(List dataList, ServletOutputStream out) throws IllegalAccessException, IOException { // 空集合直接返回 if (dataList.isEmpty()) { return; } // 获取泛型 T 的所有成员变量 List fieldList = ClassUtils.getFields(dataList.get(0).getClass()); // 建立一个 Excel 文件,并在文件中创建一个表单 HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet(); // 创建行(表头) HSSFRow row = sheet.createRow(0); // 创建单元格,并设置表头居中 HSSFCellStyle hssfCellStyle = workbook.createCellStyle(); hssfCellStyle.setAlignment(HorizontalAlignment.CENTER); // 循环设置列名 HSSFCell hssfCell; for (int i = 0; i // 添加新的一行 row = sheet.createRow(i + 1); // 获取泛型对象 T 的成员变量和值的对应关系 dataMap = ClassUtils.getFieldOfValue(dataList.get(i)); // 将数据写入该行 for (int j = 0; j // 设置 ContentType 和返回头 response.setContentType("application/binary;charset=UTF-8"); response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("导出"+new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) +".xls", "UTF-8")); //获得输出流 ServletOutputStream out = response.getOutputStream(); // 制造数据 List userList = new ArrayList(); userList.add(new User(1, "iceclean", "ice123")); userList.add(new User(2, "len", "len123")); userList.add(new User(3, "rin", "rin123")); userList.add(new User(4, "rex", "rex123")); userList.add(new User(5, "alsie", "als123")); // 输出 excel 表格数据 fileService.exportExcel(userList, out); } === Service 层 === public void exportExcel(List dataList, ServletOutputStream out) throws IOException, IllegalAccessException { FileUtils.exportExcel(dataList, out); }

Postman 上的演示: 什么值也不用传,可以看到返回的是乱码(其实是二进制流) 在这里插入图片描述 所以这里需要放到浏览器中去执行(可以用前端写个 post 方法,这里单纯使用 get 直接测试)

使用浏览器直接访问的效果: 将直接弹出个下载框 在这里插入图片描述 打开看里面的数据 在这里插入图片描述 任务圆满完成~~

▲ 与之相关的还有文件导出篇,可以看看这篇【纯干货】SSM 实现文件上传

2021-8-10 更新

对以上方法的不足之处作了改进,包括以下两点:

当字段为空时,表格中直接显示为 null,可以改进为人为指定 null 的代替值表格中的列名直接为属性英文名,可以改进为人为指定其对应的中文名称 对空值的改进

简单的改进的话,只需要找到工具类 ClassUtils.java 中的 getFieldOfValue() 方法,对里边的值作判断即可 也可以将默认值作为字段提取出来成为形参,供调用者输入,这里不作演示了

// 获取每个成员属性对应的值,并映射 for (Field field : declaredFields) { // 允许访问私有变量的值 field.setAccessible(true); // 获取属性值,并在其为空时赋予默认值 String fieldData = field.get(data).toString(); fieldData = fieldData == null ? "": fieldData; // 获取成员变量的值,并放入 map 中 fieldMap.put(field.getName(), fieldData); } 对列名的改进

① 首先添加自定义注解: 其中元注解 Target 表示注解使用在什么地方(这里设置为成员变量),Retention 设置注解在什么时候可以存在(这里设置为在运行期间可以被反射读取到)

/** * @author : Ice'Clean * @date : 2021-08-10 * * 为实体类的成员变量起名字 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface FieldName { String value() default "名字"; }

② 然后在实体类中使用该注解 自定义属性名对应的中文名称

/** * @author : Ice'Clean * @date : 2021-08-05 */ public class User { @FieldName("用户 Id") private Integer userId; @FieldName("用户名") private String userName; @FieldName("用户密码") private String userPass; //... 省略 }

③ 在 ClassUtils.java 工具类中添加以下方法

/** * 通过类型返回对应的属性名称列表 * 名称为该属性上的 FieldName(自定义注解) 的值 * @param target 目标类型 * @return 属性对应的中文名称列表 */ public static List getFieldNames(Class target) { // 获取所有成员变量名称 List fieldList = new ArrayList(); Field[] declaredFields = target.getDeclaredFields(); // 放入 List 集合中 for(Field field : declaredFields) { // 获取该成员变量注解 FieldName 的值,即其对应的中文名称 // 这里通过反射,取出了属性中的 value 值,即属性对象的中文名称 fieldList.add(field.getAnnotation(FieldName.class).value()); } return fieldList; }

④ 对核心代码进行改进 改动的地方很简单,增加一个中文名称列表(从上面方法中获得),将列名的填充值改成由该列表填充即可

/** * 将列表数据导出为 Excel 表格 * @param dataList 列表数据 * @param out 输出源 * @param 数据的类型 */ public static void exportExcel(List dataList, ServletOutputStream out) throws IllegalAccessException, IOException { // 空集合直接返回 if (dataList.isEmpty()) { return; } // 获取泛型 T 的所有成员变量 // 这里的第一种是获取原属性名,第二种是获取属性对应的注解 FieldName 的值,即对应的中文名称 List fieldList = ClassUtils.getFields(dataList.get(0).getClass()); List fieldNameList = ClassUtils.getFieldNames(dataList.get(0).getClass()); // 建立一个 Excel 文件,并在文件中创建一个表单 HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet(); // 创建行(表头) HSSFRow row = sheet.createRow(0); // 创建单元格,并设置表头居中 HSSFCellStyle hssfCellStyle = workbook.createCellStyle(); hssfCellStyle.setAlignment(HorizontalAlignment.CENTER); // 循环设置列名(这里使用注解对应的中文名) HSSFCell hssfCell; for (int i = 0; i // 添加新的一行 row = sheet.createRow(i + 1); // 获取泛型对象 T 的成员变量和值的对应关系 dataMap = ClassUtils.getFieldOfValue(dataList.get(i)); // 将数据写入该行 for (int j = 0; j


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有