若依二开:导出功能改造,让导出EXCEL 更灵活方便
最近因为交付项目忙起来没有时间更新头条,刚好项目中有导出功能。于是马上就答应客户绝对没有问题,因为心里想这功能若依框架里面不是已经做了吗,直接用不就完了,还能有啥工作量,心里暗暗自喜。
但是在真正使用的时候发现了一个大问题,客户的需求是不同页面导出的字段不一样(其实后台我是同一个表),而且这种需求还不少,反正就是不管你后台怎么设计,在不同的页面可能需要导出的数据字段多少是不一样的。比如一个历史表,在A模块里面需要导出4个字段,在B模块里面可能需要导出6个字段。咱先看一下若依里面的excel导出 是怎么用的。
这个是若依最简单的导出用法,看起来是不是很简单方便?但是你仔细看就可以看到 这个list是从数据库查出来的数据,然后
ExcelUtil
首先自己再定义一个实体类 SysConfigVo ,这个类只定义你需要导出的字段 ,然后 将 List
ExcelUtil
u.exportExcel(response, list, "参数数据");
这样做虽然解决了问题,但是感觉这种做法太过于繁琐,而且额外多了一次数据的遍历。如果是一个业务还好,要是好几个业务都需要不同的导出,这个就有点不方便了。所以这个导入工具目前来看有以下几点不足:
- 数据源和导出的模版是用一个偶合大
- 不能满足同一个数据源需要导出不同模版的需求
- 泛型导致强耦合
- 构造器参数使用泛型完全是多余的
其具体的代码如下图所示:
可以看到,构造方法的入参和数据来源的通过泛型强耦合在一起了。实际上数据源和导出模版没有类型上的绑定关系,应该通过字段名字关联就可,这样才能实现一个数据源多个模版。为了解决这个问题,我着手对这个工具类进行以下改造:
- 构造器参数不需要泛型
- 可以支持任意的模版配置
- 数据源和导出配置类没有强耦合
改造后应该支持如下面的用法:
List list = configService.selectConfigList(config);
ExcelUtil2 util = new ExcelUtil2(ConfigVo2.class);
util.exportExcel(response, list, "参数数据");
数据来源是 List
util.exportExcel(response, list, "参数数据")这个方法可以接受任意数据源。 即它和ConfigVo2不需要是同一个类型,这样就可以使用一个list 配置不同的ConfigVo2,或者ConfigVo3,ConfigVo4 ,如此就可以满足一个数据源匹配不同的导出模型了。
为了兼容之前的业务,我没有修改原来的代码,只是复制出来一个重新命名为 ExcelUtil2。下面分享一下如何改造这个工具类让它可以灵活的配置不同导出模版。
首先,为了不强类型耦合,这里要去掉泛型,然后数据源也不使用泛型,而是接受任意数据
然后就是获取数据这个方法,原来是根据属性反射获取数据(所以它会要求数据类型和excel模版类型是同一个类。也就是你必须得像下面这样创建对象:
ExcelUtil
下面是我改造后的代码截图,可以看到 这个数据是Object 任意类型,并不是T 泛型了,然后Field 和Object可以是同一个类也可以不同(但是需要有相同属性名) ,所以不能使用字段反射而是得使用方法反射。也就是通过数据源的Class 执行它的get方法获取真正的数据,而这个方法名则由Field对象提供(就是属性名称),这个Field 就是来自构造方法里面的那个配置类,这里就是解耦的关键所在。从这里也可以看出,实际上数据源是不需要关心它是什么具体类型的,只需要知道它是一个Object 就可以啦。
通过上面改造后,就可以通过一个数据源灵活的配置不同的导出模版了,如下面这样愉快的使用:
// 这个是从数据库查询出来的原始数据
List list = configService.selectConfigList(config);
// 创建对象,不需要泛型,但是需要一个导出模版的入参,这个参数来确定导出的模版格式和字段
ExcelUtil2 util = new ExcelUtil2(ConfigVo2.class);
// 这个方法可以接收SysConfig类型的 也可以接收其他任意类型的List,它和ConfigVo2可以不相同
util.exportExcel(response, list, "参数数据");
@Data
public class ConfigVo2 {
@Excel(name = "参数名称", sort = 2)
private String configName;
@Excel(name = "参数主键", cellType = Excel.ColumnType.NUMERIC, sort = 1)
private Long configId;
}
同样的数据源,咱可以导出到不同的模版中
@Data
public class ConfigVo3 {
@Excel(name = "参数键名")
private String configKey;
@Excel(name = "参数键值")
private String configValue;
}
List list = configService.selectConfigList(config);
// 这里直接使用 ConfigVo3 做导出,不需要做任何其他改动
ExcelUtil2 util = new ExcelUtil2(ConfigVo3.class);
util.exportExcel(response, list, "参数数据");
如果还有其它的导出模版,在不改变你service的前提下你只需要再创建提供模版类定义导出字段就可以了。
通过以上改造,这个导出工具就更加灵活了,适应更多的业务场景。但是从我个人角度看,又遇到另外一个问题,就是你需要建很多这种模版类,这些模版类又只使用一次,那你的代码就臃肿起来。下一期分享如何通过动态配置来如何解决这个问题。
十几年JAVA老码农,喜欢研究技术,目前是自由开发者,擅长物联网、TMS、MES、电商、在线教育项目开发,欢迎大家一起分享交流。