读取报表方式目前提供了两种形式file和definebean两种方法。file形式比较形象化易于理解,在demo中的showreport.jsp用的就是该方法。definebean的方式是通过读取缓存来得到报表的。在咱们帮助文档中做的如下介绍:
<% String reportPath = request.getRealPath(”/reportFiles/api/wangge.raq”);//取得报表真实路径
ReportDefine rd = (ReportDefine)ReportUtils.read(reportPath);
request.setAttribute(”reportDefine”,rd); //把ReportDefine对象在request中保存
%>
<report:html name=”report1″
srcType=”defineBean”
beanName=”reportDefine”
exceptionPage=”/jsp/myError.jsp” //错误提示页面
/>
这里的报表真是路径也可以通过直接从数据库中取到放在session中,直接将raq转成ReportDefine类型
(ReportDefine) request.getSession().getAttribute(”raq”);
当把ReportDefine对象放在request中保存时,定义一个beanName,如果此报表没有出现并发操作时,没有问题,一旦并发操作,这个beanName写死的话,缓存中将会被后访问的definebean替换,从而导致会出先数组越界的报错,控制台中直接显示的是在该生成HTML时报的错并没有打印sql语句。
分析原因:由于采取的是读缓存的方式来展现报表,假如A和B两张报表,同时展现出来,B比A在后台中稍微慢些,这时缓存中由于beanName相同,A的被B替换,也就是说缓存中只有B报表的缓存,这时同时对AB进行填报操作,当A提交时对应的更新属性字段取得是缓存中B报表的,这时会导致数组越界现象,也会出现填报错位,可见是读的另一张报表的缓存按这张报表展现的从而出错。
解决方法:将beanName写活,可以采取用随机数或者用System.currentTimeMillis()去时间当name等方法都可以避免beanName重复。
另外如果beanName写死的话,想通过每次清楚缓存来解决也是不可取的,这事如果在每次展现报表钱执行CacheManager.getInstance().deleteAllReport();或者其他清除缓存的操作,会导致读报表都会读到第一张报表。
















