一、简介。
多人同时导出时进行排队等候,可以自定义排队人数,在大数据情况下可以分批处理数据、导出为异步,导出过程中可获取导出进度,导出完成之后调用下载接口。
可以自定义导出的列。
二、代码实现
1、创建队列,队列是使用的java的Queue
首先先创建队列的类
@Slf4j
@Component
public class Queue {
/**
* 缓存导出的队列。数量就是你最大几个请求排队
*/
public static BlockingQueue<ColumnForm> queue = new ArrayBlockingQueue<ColumnForm>(5);
/**
* 导出的线程状态
*/
private static boolean isRunning = false;
/**
* 超时时间间隔
*/
public static long TIMEOUT_INTERVAL = 3 * 60 * 1000;
public static boolean export(CmsNewsColumnForm cmsNewsColumnForm) {
boolean rsp = false;
try {
//阻塞3秒
rsp = queue.offer(cmsNewsColumnForm, 3, TimeUnit.SECONDS);
if (!rsp) {
throw new Exception(异常信息);
}
if (!isRunning) {
startup(cmsNewsColumnForm);
isRunning = true;
}
} catch (Exception e) {
throw new Exception(异常信息);
}
return rsp;
}
public static void startup(CmsNewsColumnForm cmsNewsColumnForm) {
if (isRunning) {
return;
}
Thread th = new Thread(() -> {
long timestamp = System.currentTimeMillis();
//获取service
Service service = SpringContextUtils.getBean(Service.class);
while (isRunning) {
long timeout = timestamp + TIMEOUT_INTERVAL;
if (System.currentTimeMillis() > timeout) {
//空跑一段时间(3分钟)后线程退出
break;
}
try {
if (queue.size() == 0) {
Thread.sleep(1000);
continue;
}
//这里是你导出业务的方法
Service.export(columnForm);
queue.poll();
} catch (Exception e) {
log.error("导出出错", e);
}
}
isRunning = false;
log.debug("导出线程停止。");
});;
th.start();
}
}
2、编写实现类service。
@Autowired
private ExportThread exportThread;
public void export(ColumnForm ColumnForm) {
List<Future> futures = new ArrayList<>();
//定义文件存放的地址
File file = FileUtil.mkdir(System.getProperty("user.dir") + File.separator + "upload" + File.separator + ColumnForm.getUserId());
String filePath = file.getPath() + File.separator;
//这里是你预先设置可能会需要导出的列
LinkedHashMap<String, String> linkedHashMap = ExportDict.newsMap;
//把map变成线程安全
Map<String, String> newsMap = Collections.synchronizedMap(new LinkedHashMap<>());
//需要导出的列,前端传过来的列是驼峰的,这里我们做一个转换,把他转为下划线,方便数据库查询使用。
Map<String, String> map = new HashMap<>();
ColumnForm.getColumn().forEach(news -> {
//驼峰转下划线命名
String chang = StringUtils.toUnderScoreCase(news);
map.put(news, chang);
//构建excel表头
linkedHashMap.forEach((k, v) -> {
if (k.equals(news)) {
newsMap.put(k, v);
}
});
});
把转换好的列放进map里面
ColumnForm.setChang(map);
//下面是分批次导出
//查