java导致页面崩溃_poi导出大批量数据时导致页面崩溃处理方案

当项目中需要导出大量Excel数据时,由于响应时间过长,可能导致页面崩溃。为了解决这个问题,可以采用前端定时刷新结合进度条的方式,后端利用缓存和线程来实现数据导出。后端在接收到请求后返回进度,通过开启新线程执行查询和导出操作,当导出完成更新进度到100%,前端则关闭进度条并调用下载接口获取数据。代码示例展示了如何在Java中实现这一方案。
摘要由CSDN通过智能技术生成

问题描述:项目中导出execl数据量非常大,导致了页面长时间得不到响应而崩溃掉了,所以导出execl失败!

处理方案:前端采用定时刷新+进度条方式,后端导出采用缓存线程实现导出,导出改用每次请求后端直接返回进度条数值,开启一个线程让它去执行查询与导出操作。当导出执行完成将进度条写成100返回给前端,前端判断100后关闭进度条加载后端一个下载接口,将数据写出到浏览器

代码参考:

d886fc5268b742101b7ecc9a7efae80f.png

ad78fcce2a80bbcf35c1ed4445bbea50.png

272486de687f220fdd286409d7e42a06.png

后端代码参考:

/**

* 获取进度查询

*

* @param uuid

* @return

*/

@RequestMapping(value = "/progress", method = RequestMethod.POST)

public @ResponseBody Result progress(@RequestParam String uuid) {

Result result = new Result();

result.setData(cacheManager.get(uuid));

result.setSuccess(true);

return result;

}

/**

* 获取进度查询

*

* @param uuid

* @return

*/

@RequestMapping(value = "/progress", method = RequestMethod.POST)

public @ResponseBody Result progress(@RequestParam String uuid) {

Result result = new Result();

result.setData(cacheManager.get(uuid));

result.setSuccess(true);

return result;

}

/**

* 导出

*

* @param request

* @param response

* @return

*/

@SuppressWarnings({ "static-access", "unchecked" })

@RequestMapping(value = "/excelExport", method = RequestMethod.POST)

public @ResponseBody Result exportData(@RequestParam String exportdata,

HttpServletRequest request, HttpServletResponse response) {

Result result = new Result();

String uuid = UUID.randomUUID().toString();

result.setData(uuid);

cacheManager.setex(uuid, 0, 600);

executor.submit(new Runnable() {

@Override

public void run() {

try {

Map> exportMap = new LinkedHashMap>();

PageVO pageVO = JSONObject.parseObject(exportdata,

PageVO.class);

if (pageVO.getSearchParams() == null) {

ExceptionUtils.wrapBusinessException("当前参数数据有误");

}

List testvos = resultMapper

.getTestResultList(pageVO.getSearchParams());

cacheManager.setex(uuid, 7, 600);

for (TestResultVO vo : testvos) {

List resultVOs = vo.getResults();

StringBuffer sb = new StringBuffer(

"{'sampleno':'样品编号','samplename':'样品名称','sampledatestr':'取样日期','uploadtime':'上传时间','batch':'批次','furnaceno':'炉号','furnacetimes':'炉次'");

if (vo.getSampledate() != null) {

vo.setSampledatestr(new SimpleDateFormat(

"yyyy-MM-dd").format(vo.getSampledate()));// 将取样日期转化为yyyy-MM-dd格式导出

}

if (resultVOs != null && resultVOs.size() > 0) {

Field fields[] = vo.getClass().getDeclaredFields();

for (int i = 0; i < resultVOs.size(); i++) {

if (i == resultVOs.size() - 1) {

sb.append(",'element")

.append(i + 1)

.append("':'")

.append(resultVOs.get(i)

.getItemname()

+ "("

+ resultVOs.get(i)

.getMeasdocname()

+ ")").append("'}");

} else {

sb.append(",'element")

.append(i + 1)

.append("':'")

.append(resultVOs.get(i)

.getItemname()

+ "("

+ resultVOs.get(i)

.getMeasdocname()

+ ")").append("'");

}

// 将子表元素值反射到主表自定义字段,以便导出使用

for (Field field : fields) {

String lastzf = null;

if (i > 8) {// 将子表元素根据下标+1与主表截取最后两位相同的赋值

lastzf = field.getName().substring(

field.getName().length() - 2);

} else {// 将子表元素根据下标+1与主表截取最后一位相同的赋值

lastzf = field.getName().substring(

field.getName().length() - 1);

}

if (NumberUtils.isDigits(lastzf)) {// 判断该类型是否为整数字符串

if (Integer.valueOf(lastzf) == i + 1) {

field.setAccessible(true);

field.set(vo, resultVOs.get(i)

.getConfirmvalue());

field.setAccessible(false);

}

}

}

}

} else {

sb.append("}");

}

List list = new ArrayList();

list.add(vo);

Boolean falg = true;// 这段逻辑处理不同元素名称,相同元素个数的情况

for (Map.Entry> enMap : exportMap

.entrySet()) {

if (enMap.getKey().contains(sb.toString())) {

falg = false;

enMap.getValue().addAll(list);

}

}

if (falg) {

exportMap.put(sb.toString(), list);

}

}

// }

// 获取浏览器信息,对文件名进行重新编码

String fileName = "化验结果查询"+uuid+".xlsx";

File directory = new File("");// 参数为空

String courseFile = directory.getCanonicalPath();

isDirExist(courseFile + "/export");

String path = courseFile

+ "/export/" + fileName;

OutputStream os = new FileOutputStream(path);

ExcelExportImportUtils.ListtoExecl(exportMap, os,uuid);

//因为分布式原因将流转成二进制存入缓存,进度条100时直接取缓存值

FileInputStream input = new FileInputStream(path);

byte[] b = InputStreamToByte(input);

cacheManager.setex(qcTestResultURL+uuid,b, 600);

cacheManager.setex(uuid, 100, 600);

File file = new File(path);

input.close();

//删除服务器文件

file.delete();

os.flush();

os.close();

} catch (Exception e) {

e.printStackTrace();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值