积木报表导出数据量太大报错问题处理
- 问题背景
- 解决方案
- 运行结果
- 关键代码
问题背景
积木报表在导出大量数据时可能会遇到报错,这通常是由于数据量大导致的性能问题或数据处理方式不当引起的。以下是一些可能导致报错的原因及相应的解决方法:
性能问题:当数据量非常大时,积木报表在导出过程中可能会遇到性能瓶颈,导致导出过程缓慢甚至失败。这可能是因为报表工具本身或其所依赖的库(如Apache POI)在处理大量数据时的性能不足。解决这一问题的方法包括优化SQL查询、调整分页大小、使用更适合处理大量数据的库(如阿里巴巴的EasyExcel)进行导出,或者采用异步处理的方式来避免接口超时1。
数据处理方式:如果待导出的数据包含特殊字符,如英文双引号或等号,这可能导致JSON反序列化报错。这种情况下,需要检查业务数据,确保数据格式正确,避免包含可能导致报错的特殊字符23。
内存溢出:如果报表工具或其依赖的库不支持流式(分批)导出,大量数据的处理可能会导致内存溢出。解决这一问题的方法包括使用流式导出的方式,或者检查报表工具是否支持异步分页呈现和流式(分批)导出Excel的功能4。
综上所述,解决积木报表在导出大量数据时报错的问题,需要从优化数据处理方式、调整导出设置、以及确保数据格式正确等方面入手。通过这些方法,可以有效提高报表导出的稳定性和性能。
解决方案
1、在项目中写个拦截器,拦截积木报表导出接口
2、获取到积木报表查询的数据,自己实现导出功能,这里我使用的是阿里的easyExcel导出
实现结果
关键代码
1、添加拦截器
拦截积木报表导出接口/jmreport/exportAllExcelStream
@Component
@Slf4j
public class ExportExcelInterceptor implements HandlerInterceptor {
@Autowired
private ExportUtil exportUtil;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
if (requestURI.endsWith("/jmreport/exportAllExcelStream")) {
// 在这里执行拦截逻辑,例如验证用户权限、记录日志等
log.info("Intercepted request: {}" , requestURI);
exportUtil.exportExcel(request, response, handler);
return false;
// 返回true表示继续处理请求,返回false表示中断请求处理
}
return true;
// 对于其他请求,不进行拦截
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 请求处理完成后的逻辑,如果需要的话
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 请求完成后的逻辑,如果需要的话
}
}
2、注入拦截器
在这里插入代码片
3、实现导出
@Component
@Slf4j
public class ExportUtil {
@Autowired
private e jmReportDesignService;
@Autowired
private JmReportBaseConfig jmBaseConfig;
@Autowired
private JimuReportDbDao jimuReportDbDao;
@Autowired
private JimuReportDao reportDao;
@Autowired
private IJimuReportService jimuReportService;
public void exportExcel(HttpServletRequest request, HttpServletResponse response, final Object handler) throws Exception{
response.setCharacterEncoding("utf-8");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.addHeader("Content-Disposition", "attachment;filename=jmexport.xlsx");
log.info("===========exportAllExcelStream 执行导出EXCEL action ==========");
HashMap map = new HashMap(request.getParameterMap());
// 获取请求参数
StringBuilder body = new StringBuilder();
String line;
try (BufferedReader reader = request.getReader()) {
while ((line = reader.readLine()) != null) {
body.append(line);
}
}
JSONObject jsonObject = JSONObject.parseObject(body.toString());
boolean isToken = map.containsKey("token");
if (isToken) {
map.remove("token");
}
String excelConfigId = jsonObject.getString("excelConfigId");
JSONObject queryParam = jsonObject.getJSONObject("queryParam");
Map<String, Object> resMap = this.d(excelConfigId);
List downCodeList = (List)resMap.get("downCodeList");
Integer var16 = this.jmBaseConfig.getPageSizeNumber();
this.getData(response, excelConfigId, queryParam, downCodeList, var16);
}
public Map<String, Object> getData(HttpServletResponse response, String var1, JSONObject var2, List<String> var3, int var5)
throws IOException {
HashMap var6 = new HashMap(5);
log.debug("数据源集合数据::" + var3);
JSONObject jsonObject = new JSONObject();
boolean isonly = false;
if (null != var2) {
jsonObject = JSON.parseObject(var2.toJSONString());
jsonObject.put("pageSize", var5);
isonly = "1".equals(jsonObject.getString("onlyPageData"));
}
JimuReport jimuReport = this.reportDao.get(var1);
String jsonStr = jimuReport.getJsonStr();
this.jsonStr(jsonObject, jsonStr);
Map reportData = jimuReportService.getDataById(jimuReport, jsonObject, isonly, var3);
this.getMapData(jsonStr, reportData);
jimuReport.setDataList(reportData);
ReportDbInfo reportDbInfo = (ReportDbInfo)reportData.get("project_info");
List<Map<String, Object>> list = reportDbInfo.getList();
JSONObject var11 = JSON.parseObject(jsonStr);
JSONObject var12 = var11.getJSONObject("rows");
if (var12.containsKey("-1")) {
var12.remove("-1");
}
if (var12.containsKey("len")) {
var12.remove("len");
}
JSONObject jsonObject1 = var11.getJSONObject("rows").getJSONObject("2").getJSONObject("cells");
List<Integer> keyList = new ArrayList<>();
jsonObject1.keySet().forEach(key -> {
keyList.add(Integer.valueOf(key));
});
List<List<String>> headList = new ArrayList<>();
for (int i = 1; i <= keyList.size(); i++) {
headList.add(Arrays.asList(jsonObject1.getJSONObject(String.valueOf(i)).getString("text")));
}
List<List<Object>> dataList = new ArrayList<>();
for (Map<String, Object> map : list) {
List<Object> values = new ArrayList<>();
map.keySet().forEach(key->{
values.add(map.get(key));
});
dataList.add(values);
}
EasyExcel.write(response.getOutputStream()).head(new ArrayList<>())
.sheet("sheet")
.doWrite(dataList);
return var6;
}
private void jsonStr(JSONObject var1, String var2) {
if (var1.containsKey("jmViewFirstLoad") && String.valueOf(1).equals(var1.getString("jmViewFirstLoad"))) {
JSONObject var3 = JSONObject.parseObject(var2);
if (var3.containsKey("rpbar")) {
JSONObject var4 = var3.getJSONObject("rpbar");
if (var4.containsKey("pageSize")) {
Integer var5 = var4.getInteger("pageSize");
if (var5 != null && !"".equals(var5)) {
var1.put("pageSize", var5);
}
}
}
}
}
private void getMapData(String var1, Map<String, Object> var2) {
JSONObject var3 = JSON.parseObject(var1);
if (var3.containsKey("completeBlankRowList")) {
JSONArray var4 = var3.getJSONArray("completeBlankRowList");
if (var4.size() > 0) {
Iterator var5 = var2.keySet().iterator();
while(true) {
Object var11;
int var12;
JSONObject var13;
Integer var17;
int var19;
do {
Object var18;
do {
String var6;
do {
do {
JSONObject var7;
do {
if (!var5.hasNext()) {
return;
}
var6 = (String)var5.next();
var7 = null;
for(int var8 = 0; var8 < var4.size(); ++var8) {
JSONObject var9 = var4.getJSONObject(var8);
if (var9.getString("db").equals(var6)) {
var7 = var9;
break;
}
}
} while(var7 == null);
var17 = var7.getInteger("rows");
} while(var17 == null);
} while(var17 <= 0);
var18 = var2.get(var6);
} while(!(var18 instanceof ReportDbInfo));
ReportDbInfo var10 = (ReportDbInfo)var18;
var11 = var10.getList();
var12 = ((List)var11).size();
var13 = new JSONObject();
if (var11 == null) {
var11 = new ArrayList();
} else if (var12 != 0) {
Map var14 = (Map)((List)var11).get(0);
Iterator var15 = var14.keySet().iterator();
while(var15.hasNext()) {
String var16 = (String)var15.next();
var13.put(var16, "");
}
}
var19 = var12 % var17;
} while(var19 <= 0 && var12 != 0);
for(int var20 = var17 - var19; var20 > 0; --var20) {
((List)var11).add(var13);
}
}
}
}
}
public void a(List<String> var1, String var2, Map<String, Object> var3) {
ArrayList var4 = new ArrayList();
int var5 = 0;
boolean var6 = false;
String var7 = "";
ArrayList var8 = new ArrayList();
ArrayList var9 = new ArrayList();
Iterator var10 = var1.iterator();
while(true) {
while(var10.hasNext()) {
String var11 = (String)var10.next();
JmReportDb var12 = this.jimuReportDbDao.getReportDb(var2, var11);
if (null == var12) {
var1.remove(var11);
} else {
DbModel var13 = new DbModel();
var13.setCode(var11);
var13.setOrder(var5);
if ("1".equals(var12.getIsPage())) {
var6 = true;
var7 = var11;
var13.setPage(true);
} else {
var13.setPage(false);
}
if (var6 && !"1".equals(var12.getIsPage())) {
var9.add(var11);
} else if (!var6 && !"1".equals(var12.getIsPage())) {
var8.add(var11);
}
var4.add(var13);
var13 = null;
++var5;
}
}
var3.put("moredbSource", var6);
var3.put("downCodeList", var9);
var3.put("upCodeList", var8);
var3.put("pageCode", var7);
var3.put("dbList", var4);
return;
}
}
private Map<String, Object> d(String var1) {
JimuReport var2 = this.jmReportDesignService.getById(var1);
List var3 = this.jimuReportDbDao.selectList(var1);
ArrayList var4 = new ArrayList();
Iterator var5 = var3.iterator();
while(var5.hasNext()) {
JmReportDb var6 = (JmReportDb)var5.next();
var4.add(var6.getDbCode());
}
String var19 = var2.getJsonStr();
ArrayList var20 = new ArrayList();
JSONObject var7 = JSONObject.parseObject(var19);
JSONObject var8 = var7.getJSONObject("rows");
var8 = this.c(var8);
Iterator var9 = var8.keySet().iterator();
label80:
while(true) {
String var10;
int var11;
do {
do {
do {
do {
do {
if (!var9.hasNext()) {
HashMap var21 = new HashMap(5);
this.a((List)var20, (String)var1, (Map)var21);
return var21;
}
var10 = (String)var9.next();
} while("cells".equals(var10));
} while("isDrag".equals(var10));
} while("len".equals(var10));
} while("-1".equals(var10));
var11 = Integer.parseInt(var10);
} while(var11 < 0);
JSONObject var12 = var8.getJSONObject(var10).getJSONObject("cells");
var12 = this.c(var12);
Iterator var13 = var12.keySet().iterator();
while(true) {
String var14;
do {
if (!var13.hasNext()) {
continue label80;
}
var14 = (String)var13.next();
} while("-1".equals(var14));
JSONObject var15 = var12.getJSONObject(var14);
Object var16 = var15.get("text");
boolean var17 = g.d(var16) && (var16.toString().contains("#{") || var16.toString().contains("${"));
if (var17) {
String var18 = var16.toString();
var18 = var18.replace("${", "").replace("#{", "");
if (var18.contains(".")) {
var18 = var18.substring(0, var18.indexOf("."));
}
if (!var20.contains(var18) && var4.contains(var18)) {
var20.add(var18);
}
}
}
}
}
private JSONObject c(JSONObject var1) {
ArrayList var2 = new ArrayList();
Collections.sort(var2);
JSONObject var9 = new JSONObject(true);
JSONObject var7;
for(Iterator var5 = var2.iterator(); var5.hasNext(); var7 = null) {
Integer var6 = (Integer)var5.next();
var7 = var1.getJSONObject(String.valueOf(var6));
var9.put(String.valueOf(var6), var7);
}
return var9;
}