*前言
我们在做web项目时,业务需求做的最多的就是查询,既然有查询,难免就有导出。如果给每个查询界面都写一个导出未免有点不够优雅,代码会变得很臃肿冗余,虽然可以把一些公共的生成excel、写入excel、下载等等写成统一的工具类,但是数据库查询sql的代码和调用工具类的代码还是没有办法省略的。另外,同步请求中,碰到要导出几十万那种大量的数据时,代码也会一直卡在查询和生成的地方,没有办法做其他事情,给用户的体验也不好。为此,我们可以换一种思路,写一个异步的统一的查询、 生成、下载报表的公共模块。
*包含的部分
为了实现这个统一导出模块,我们最少需要的部分有:
A.至少一个已经存在了的查询
B.一个统一的用于报表导出申请任务的后台服务
C.一张专门用于记录导出任务的数据库表
D.一个专门的报表生成的调度部分
E.真正的生成报表的实现
F.用于存放生成的报表的文件地址
G.一个统一的报表任务查询界面
*具体流程
在A中一定有个导出按钮,我们可以把这个按钮的请求地址改为B的地址,并且请求中至少包含以下两个参数:需要导出的报表类型(可以为查询的后台地址或者SpringBean的名称)和查询的参数。B在收到A传入的参数后可以直接把A的参数直接保存到到C中(C至少需要保存以下数据:导出的报表类型、查询的参数、导出时间、报表生成状态以及导出申请的唯一流水号),状态就默认为末完成。保存成功之后就用到了D,D会去每几分钟就去查一次C 中未完成的申请任务,查询出之后把任务设置为正在执行,防止重复生成,并且把这些任务都交给E来处理,其中如果任务比较多我们可以综合服务器的硬件情况使用线程池异步来处理生成。E就根据报表类型和前台传过来的参数去调用要生成报表的查询地址(如果存的是查询请求地址,可以直接http调用,如果是bean名称,可以在Spring容器中获取这个bean然后调用),如果碰到分页的情况下,我们尽量给一个比较大的每页容量,由于是一个项目,分页返回参数基本上都类似,我们就可以判断第一次查询是否已经把所有数据查完,若没有查完就继续查。如果查出来的数据过多,我们可以分批写入excel并释放内存防止oom,其中的工具类用easyexcel或者poi都可以,对于表头的处理的话如果使用的带有注解的实体类,可以通过反射读取注解的内容来写入表头,如果是自己写的表头,可以在查询的bean中继承一个自定义接口,这个接口只有一个方法,那就是用来将所有的表头添加到list中并返回,这样在生成的时候先去把bean转化成我们自定义的接口,然后调用那个返回表头的方法并写入表头即可。写入excel完成后可以把文件直接存到F中,并且把C中的状态设置为已完成。用户下载我们生成好的报表是在G中,在G中就是一个对于C表的查询功能,可以根据生成状态、申请的唯一流水号、时间、申请类型等来查询数据,还需要在G中添加一个下载按钮,点击下载,就去文件路径中把生成好的excel下载到浏览器中。
*影响
如果使用统一生成导出报表方案,对于用户的感知只是换了一个地方下载报表,并且有几分钟的延迟,但是对于开发者来说可以大大的提升开发效率,每次前端只需要调用公共的后台申请地址,不必在导出这种无聊的代码上浪费时间,并且对于代码的可读性和可维护性有很大的提升。如果业务人员可以接受还是一个很不错的方案。
标签:Web,报表,方案,excel,导出,表头,生成,查询 From: https://www.cnblogs.com/lrxsznbe/p/16851973.html