- 遇到一个新需求, 关联12张表进行数据查询, 大概150个字段,然后导出xls。 大概的数据1W 左右。 于是想到了三种方法;
- JEECGBOOT 在线报表--------- 直接SQL 报错,放弃了
- 积木报表---------- 采用分页, 能显示数据,但是导出xls 10分钟都没有结果;也放弃了
- 模板导出---------- 最后一条路了,必须要能用呀。 结果 10M 一个问题,客户端等待导出还是不太理想
必须要改造一下了。于是想到了任务模式,客户发起一下导出任务,然后等待后台生成好了再下载。
- 首先建立一个任务列表的增删改查
- 业务模块需要增加一个 button ,来实现业务逻辑
- 跳转到 任务列表,然后等待执行结束,点击下载按钮
@RequestMapping(value = "/exportBigXls")
public Result<?> exportBigXls(HttpServletRequest request, CommTask commTask) throws Exception {
//新建一条任务记录 获取组装需要的相关数据 模板地址 输出路径地址
long time=System.currentTimeMillis();
String templatepath="templates/temp.xlsx";
String filename=time+".xlsx";
String filepath="templates/";
CommTask comm =new CommTask();
comm.setTaskid(time+"");
comm.setState("处理中...");
comm.setPath("");
commTaskService.save(comm);
log.debug("数据保存成功:"+comm.getId());
WriteFile file=new WriteFile(templatepath,filename,filepath,commTaskService,comm);
file.start();
return Result.OK("任务加载成功,前往任务列表进行数据处理!");
}
也不是很复杂,生成文件,需要写一个新线程的类。
package org.jeecg.modules.demo.commtask.service;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.poi.ss.usermodel.Workbook;
import org.jeecg.modules.demo.commtask.entity.CommTask;
import org.jeecgframework.poi.excel.ExcelExportUtil;
import org.jeecgframework.poi.excel.entity.TemplateExportParams;
public class WriteFile extends Thread{
private String templatepath;
private String filename;
private String filepath;
private ICommTaskService commTaskService;
private CommTask commtask;
//构造函数
public WriteFile(String templatepath,String filename,String filepath,ICommTaskService commTaskService,CommTask comm) {
this.templatepath=templatepath;
this.filename=filename;
this.filepath=filepath;
this.commTaskService=commTaskService;
this.commtask=comm;
}
@Override
public void run() {
System.out.println("==========写文件线程开始启动!==========");
TemplateExportParams params =new TemplateExportParams(templatepath);
Map<String, Object> map = new HashMap<String, Object>();
map.put("title", "员工个人信息");
map.put("name", "大熊");
map.put("age", 22);
map.put("company", "北京机器猫科技有限公司");
map.put("date", "2020-07-13");
Workbook workbook = ExcelExportUtil.exportExcel(params, map);
File savefile = new File(filepath);
if (!savefile.exists()) {
savefile.mkdirs();
}
try {
FileOutputStream fos = new FileOutputStream(filepath+filename);
workbook.write(fos);
fos.close();
}catch(Exception ex) {
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
commtask.setEndTime(new Date());
commtask.setPath(filepath+filename);
commtask.setState("完成");
commTaskService.updateById(commtask);
}
}
具体的逻辑,根据自己的需要写就可以了。
记录一下前端vue的坑 定时任务setInterval 的用法。 前端页面需要刷新。 当然,非常好的办法是实现消息机制,这样实现最好。但是懒的很,先刷新页面吧。
export default {
name: 'CommTaskList',
mixins:[JeecgListMixin, mixinDevice],
components: {
CommTaskModal
},
data () {
return {
description: '文件下载任务管理页面',
// 表头
columns: [
{
title: '#',
dataIndex: '',
key:'rowIndex',
width:60,
align:"center",
customRender:function (t,r,index) {
return parseInt(index)+1;
}
},
{
title:'任务编号',
align:"center",
dataIndex: 'taskid'
},
{
title:'状态',
align:"center",
dataIndex: 'state'
},
{
title:'下载路径',
align:"center",
dataIndex: 'path'
},
{
title:'结束时间',
align:"center",
dataIndex: 'endTime'
},
{
title:'备注',
align:"center",
dataIndex: 'remark'
},
{
title: '操作',
dataIndex: 'action',
align:"center",
fixed:"right",
width:147,
scopedSlots: { customRender: 'action' }
}
],
url: {
list: "/commtask/commTask/list",
delete: "/commtask/commTask/delete",
deleteBatch: "/commtask/commTask/deleteBatch",
exportXlsUrl: "/commtask/commTask/exportXls",
importExcelUrl: "commtask/commTask/importExcel",
myTask:"/commtask/commTask/exportBigXls"
},
dictOptions:{},
superFieldList:[],
timer: '',
}
},
created() {
this.getSuperFieldList();
this.A();
},
computed: {
importExcelUrl: function(){
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
},
},
methods: {
initDictConfig(){
},
myTask(){
getAction(this.url.myTask).then((res) => {
this.msg = res.result;
if (res.success) {
this.$message.success(this.msg);
}else{
this.$message.warning(this.msg);
}
})
},
down(record){
var file=record.path;
if(file==''){
this.$message.warning("任务执行中");
}else{
//下载文件
window.open(file);
}
},
newData(){
this.loadData();
},
getSuperFieldList(){
let fieldList=[];
fieldList.push({type:'string',value:'taskid',text:'任务编号',dictCode:''})
fieldList.push({type:'string',value:'state',text:'状态',dictCode:''})
fieldList.push({type:'string',value:'path',text:'下载路径',dictCode:''})
fieldList.push({type:'datetime',value:'endTime',text:'结束时间'})
fieldList.push({type:'string',value:'remark',text:'备注',dictCode:''})
this.superFieldList = fieldList
}
},
mounted() {
this.timer = setInterval(this.newData, 5000);
},
beforeDestroy() {
clearInterval(this.timer);
}
}
需要注销, 要不然一直执行。 vue 用的时间不长,第一次遇到。
最后的一点思考,如果 xls 文件非常大,可以继续分割文件,生成多个文件来实现。
版权声明:本文为qianlei0007原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。