BIRT从4.4迁移至4.9时资源路径归一化至null报错求助
BIRT 4.4迁移至4.9后报表布局打开报错分析
问题描述
将BIRT从4.4版本迁移至4.9版本后,运行报表并打开布局时触发错误:The resource path [ /…/…]has been normalized to null which is not valid
相关代码片段
InputStream fileLayout = new ByteArrayInputStream(EntityUtils.toByteArray(methodLayoutReport.getEntity())); String reportEnder = servlet.getRealPath("Report/include/glw/view/report") + "/" + reportName + ".rptdesign"; design = birtReportEngine.openReportDesign(reportEnder, fileLayout);// 报错行
完整错误堆栈
INFO: Server startup in [23135] milliseconds java.lang.IllegalArgumentException: The resource path [/WEB-INF/classes/…/…/…/…/estrutura/est_report_library_base.rptlibrary] has been normalized to [null] which is not valid at org.apache.catalina.webresources.StandardRoot.validate(StandardRoot.java:266) at org.apache.catalina.webresources.StandardRoot.getResource(StandardRoot.java:212) at org.apache.catalina.webresources.StandardRoot.getClassLoaderResource(StandardRoot.java:225) at org.apache.catalina.loader.WebappClassLoaderBase.findResource(WebappClassLoaderBase.java:954) at org.apache.catalina.loader.WebappClassLoaderBase.getResource(WebappClassLoaderBase.java:1078) at org.eclipse.birt.report.model.util.ResourceLocatorImplBase.tryFragmentSearch(ResourceLocatorImplBase.java:289) at org.eclipse.birt.report.model.util.ResourceLocatorImplBase.getResource(ResourceLocatorImplBase.java:179) at org.eclipse.birt.report.model.util.ResourceLocatorImplBase.findResource(ResourceLocatorImplBase.java:80) at org.eclipse.birt.report.model.core.ModuleImpl.findResource(ModuleImpl.java:1181) at org.eclipse.birt.report.model.parser.IncludedLibrariesStructureListState$IncludedLibraryStructureState.end(IncludedLibrariesStructureListState.java:99) at org.eclipse.birt.report.model.util.XMLParserHandler.endElement(XMLParserHandler.java:177) at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source) at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source) at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source) at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source) at org.apache.xerces.parsers.XMLParser.parse(Unknown Source) at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source) at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source) at org.apache.xerces.jaxp.SAXParserImpl.parse(Unknown Source) at org.eclipse.birt.report.model.parser.ModuleReader.readModule(ModuleReader.java:94) at org.eclipse.birt.report.model.parser.DesignReader.read(DesignReader.java:81) at org.eclipse.birt.report.model.core.DesignSessionImpl.openDesign(DesignSessionImpl.java:293) at org.eclipse.birt.report.model.api.SessionHandleImpl.openDesign(SessionHandleImpl.java:257) at org.eclipse.birt.report.model.api.SessionHandle.openDesign(SessionHandle.java:1) at org.eclipse.birt.report.engine.parser.ReportParser.getDesignHandle(ReportParser.java:136) at org.eclipse.birt.report.engine.api.impl.ReportEngineHelper.getReportDesignHandle(ReportEngineHelper.java:211) at org.eclipse.birt.report.engine.api.impl.ReportEngineHelper.openReportDesign(ReportEngineHelper.java:223) at org.eclipse.birt.report.engine.api.impl.ReportEngineHelper.openReportDesign(ReportEngineHelper.java:156) at org.eclipse.birt.report.engine.api.impl.ReportEngine.openReportDesign(ReportEngine.java:307) at br.com.ipm.report.servlet.WebReport.doPost(WebReport.java:93) at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:239) at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:215) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:199) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Thread.java:834)
问题原因分析
- 路径校验严格性提升:BIRT 4.9依赖的Tomcat版本(通常为9+)对资源路径规范化的校验远严于旧版本。报错路径中包含过多
../(显示为…),规范化后超出Web应用根目录范围,被Tomcat判定为无效路径返回null。 - 报表库引用路径错误:
.rptdesign文件中引用的est_report_library_base.rptlibrary使用了错误的相对路径层级,导致BIRT引擎查找资源时生成越界路径。 getRealPath不可靠:代码中使用servlet.getRealPath()获取物理路径,该方法在部分部署场景(如war包不解压、容器自定义配置)下会返回不准确的路径,进一步干扰资源定位。
解决方案建议
- 修正报表库引用路径:打开
.rptdesign文件,调整库引用为正确的相对路径(相对于报表设计文件),或使用类路径绝对路径(如/estrutura/est_report_library_base.rptlibrary,确保库文件放在WEB-INF/classes/estrutura目录下)。 - 替换
getRealPath:改用getServletContext().getResourceAsStream()通过类加载器获取资源,或自定义BIRT的ResourceLocator实现资源查找逻辑。 - 规范化路径:确保传递给BIRT引擎的所有资源路径提前完成规范化处理,避免出现过多
../导致路径越界。
内容的提问来源于stack exchange,提问作者Murilo Costa Bittencourt
相关产品推荐
相关产品推荐

