领先一步
VMware 提供培训和认证,为您的进步加速。
了解更多作者:Jason Weathersby 和 Josh Long
开发人员使用 BIRT 在 Java/Java EE 环境中构建和部署报表。在 BIRT 3.7 中,提供了一个新的基于 POJO 的运行时环境,大大简化了 BIRT 引擎的部署。本文讨论了使用 Spring Framework 组件的几种 BIRT 集成场景。
BIRT 项目包括以下关键组件:
Spring 框架是架构和实现方法流行的集合,可使企业级 Java 开发更加容易。该框架的核心部分是依赖注入和面向切面编程。利用这些特性可以减少应用程序基础设施特定部分与业务功能(这是其主要目标)之间的耦合。Spring 框架由 VMware 内的 SpringSource 业务部门(原 SpringSource 公司于 2009 年被 VMware 收购)以开源方式开发。它在 Java 开发社区中得到广泛使用,并可在所有平台上运行,包括 VMware 支持的 Tomcat 版本,称为 tcServer。
虽然 Spring Framework 提供了许多有用的功能,但关于与 BIRT 集成的大多数问题都围绕着 Spring MVC 和在报表内访问 Spring Bean。本文涵盖了三种场景:
本文假定读者具备 BIRT 和 Spring Framework 的编程知识。要了解有关 Spring 框架的更多信息,请查看“Green Beans”博客系列。
每种场景都有一个与本文关联的示例,该示例是使用以下组件构建和测试的:
这些示例旨在进行说明,包含很少的错误检查。
在整篇文章中,不同的集成场景都引用了一个通用的 Spring Bean,该 Bean 为 BIRT 报表提供数据。Spring Framework 包含许多复杂的数据访问组件,但这个简单的示例是学习更复杂场景的有用工具。在示例代码中,有两个包:org.eclipse.birt.spring.example 和 org.eclipse.birt.spring.core。示例包包含可以替换为您自己的数据访问对象的简单代码。核心包包含用于运行和渲染 BIRT 报表的 Spring View,一个参数转换器类用于将 URL 中输入的报表参数转换为相应的 BIRT 报表参数类型,以及一个 BIRT 引擎工厂,该工厂向其他 Bean 提供 Report Engine。示例类如下所示,并在本文中使用。核心类将在下一节中描述。
我们从一个简单的 POJO 开始,它将在我们的 BIRT 报表中使用。它命名为 Car,包含描述汽车的简单属性。
package org.eclipse.birt.spring.example; public class Car{ private String make; private String model; private String year; public String getMake() { return make; } public void setMake(String make) { this.make = make; } public String getModel() { return model; } public void setModel(String model) { this.model = model; } public String getYear() { return year; } public void setYear(String year) { this.year = year; } public Car() { } public String toString(){ return "Make:--"+this.make+" Model:--"+this.model+" Year:--"+this.year; } public String getCarString(){ return( this.toString() ); } }
示例提供了一个服务类,用于加载多个 Car POJO 以用于报表目的。
package org.eclipse.birt.spring.example; import java.util.*; public class CarServiceImpl implements CarService { public ListgetAllCars (){ Car car1 = new Car(); car1.setYear("2000"); car1.setMake("Chevrolet"); car1.setModel("Corvette"); Car car2 = new Car(); car2.setYear("2005"); car2.setMake("Dodge"); car2.setModel("Viper"); Car car3 = new Car(); car3.setYear("2002"); car3.setMake("Ford"); car3.setModel("Mustang GT"); List cars = Arrays.asList( car1, car2, car3 ) ; return cars ; } }
为了在 Spring Context 中使此服务可用,我们使用一个简单的类,该类使用 Spring 注解进行配置。
package org.eclipse.birt.spring.example; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class BirtDataServiceConfiguration { @Bean public CarService carService(){ return new CarServiceImpl(); } }
有许多方法可以将 BIRT 引擎集成到 Spring 中,特别是 Spring MVC。对于本例,我们实现了一个 Spring View,它使用参数来确定用户所需的报表和输出格式。BIRT 报表引擎被注入到 View 中,以执行报表的实际运行和渲染。
BIRT 引擎可以被多个线程使用,但启动通常很耗时。理想情况下,我们只希望在应用程序生命周期内启动 BIRT 引擎一次。我们还希望在应用程序关闭时正确地关闭引擎。考虑到这一点,我们首先创建了一个 BirtEngineFactory 类,它充当工厂 Bean,其他 Bean 可以使用它来返回 BIRT 报表引擎的实例。在 Spring 中,FactoryBean 接口是复杂对象的智能构造器。它有一个重要的契约:从其 getObject 方法返回一个随时可用的对象。
package org.eclipse.birt.spring.core; import java.io.File; import java.io.IOException; import org.eclipse.birt.core.exception.BirtException; import org.eclipse.birt.core.framework.Platform; import org.eclipse.birt.report.engine.api.EngineConfig; import org.eclipse.birt.report.engine.api.IReportEngine; import org.eclipse.birt.report.engine.api.IReportEngineFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.FactoryBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.core.io.Resource; import org.springframework.util.Assert; /** Factory bean for the instance of the {@link IReportEngine report engine}. */ public class BirtEngineFactory implements FactoryBean, ApplicationContextAware, DisposableBean { public boolean isSingleton(){ return true ; } private ApplicationContext context ; private IReportEngine birtEngine ; private Resource logDirectory ; private File _resolvedDirectory ; private java.util.logging.Level logLevel ; public void setApplicationContext(ApplicationContext ctx){ this.context = ctx; } public void destroy() throws Exception { birtEngine.destroy(); Platform.shutdown() ; } public void setLogLevel( java.util.logging.Level ll){ this.logLevel = ll ; } public void setLogDirectory( org.springframework.core.io.Resource resource ){ File f=null; try { f = resource.getFile(); validateLogDirectory(f); this._resolvedDirectory = f ; } catch (IOException e) { throw new RuntimeException( couldnt set the log directory); } } private void validateLogDirectory (File f) { Assert.notNull ( f , " the directory must not be null"); Assert.isTrue(f.isDirectory() , " the path given must be a directory"); Assert.isTrue(f.exists() , "the path specified must exist!"); } public void setLogDirectory ( java.io.File f ){ validateLogDirectory(f) ; this._resolvedDirectory = f; } public IReportEngine getObject(){ EngineConfig config = new EngineConfig(); //This line injects the Spring Context into the BIRT Context config.getAppContext().put("spring", this.context ); config.setLogConfig( null != this._resolvedDirectory ? this._resolvedDirectory.getAbsolutePath() : null , this.logLevel); try { Platform.startup( config ); } catch ( BirtException e ) { throw new RuntimeException ( "Could not start the Birt engine!", e) ; } IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY ); IReportEngine be = factory.createReportEngine( config ); this.birtEngine = be ; return be ; } @Override public Class getObjectType() { return IReportEngine.class; } }
该类还实现了 DisposableBean 接口,以便在应用程序关闭时可以正确关闭引擎。当 Spring ApplicationContext 关闭时,Spring 会调用所有实现 DisposableBean 的 Bean 上的 DisposableBean#destroy 方法。我们的实现调用了 destroy 方法。最后,该类实现了 ApplicationContextAware 接口,以接收 Spring ApplicationContext 的实例。我们存储 ApplicationContext,然后使用以下代码将其传递给 BIRT Report Engine:
EngineConfig config = new EngineConfig(); //This line injects the Spring Context into the BIRT Context config.getAppContext().put("spring", this.context );
此代码将允许从 BIRT Scripting 和 Expressions 内部访问 Spring Context 对象。
接下来,我们创建一个 Spring View,它运行并渲染报表。此 View 期望注入 BIRT 报表引擎。该 View 搜索请求中的 ReportName 和 ReportFormat 参数,以决定运行哪个报表以及需要什么格式。请求中还会搜索报表参数名称。如果找到,这些报表参数将设置为相应的值。此 View 的一部分如下所示。有关更多信息,请参阅示例代码。
/** * BirtView is used to run and render BIRT reports. * This class expects the request to contain a ReportName and ReportFormat * parameter. In addition Report parameters are automatically searched for in the * the request object. */ public class BirtView extends AbstractView { public static final String PARAM_ISNULL = "__isnull"; public static final String UTF_8_ENCODE = "UTF-8"; private IReportEngine birtEngine; private String reportNameRequestParameter = ReportName ; private String reportFormatRequestParameter = ReportFormat ; private IRenderOption renderOptions ; public void setRenderOptions(IRenderOption ro) { this.renderOptions = ro; } public void setReportFormatRequestParameter( String rf ){ Assert.hasText( rf , the report format parameter must not be null) ; this.reportFormatRequestParameter = rf ; } public void setReportNameRequestParameter ( String rn ) { Assert.hasText( rn , the reportNameRequestParameter must not be null) ; this.reportNameRequestParameter = rn ; } protected void renderMergedOutputModel( Map map, HttpServletRequest request, HttpServletResponse response) throws Exception { String reportName = request.getParameter( this.reportNameRequestParameter ); String format = request.getParameter( this.reportFormatRequestParameter ); ServletContext sc = request.getSession().getServletContext(); if( format == null ){ format="html"; } IReportRunnable runnable = null; runnable = birtEngine.openReportDesign( sc.getRealPath("/Reports")+"/"+reportName ); IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask(runnable); runAndRenderTask.setParameterValues(discoverAndSetParameters( runnable, request )); response.setContentType( birtEngine.getMIMEType( format )); IRenderOption options = null == this.renderOptions ? new RenderOption() : this.renderOptions; if( format.equalsIgnoreCase("html")){ HTMLRenderOption htmlOptions = new HTMLRenderOption( options); htmlOptions.setOutputFormat("html"); htmlOptions.setOutputStream(response.getOutputStream()); htmlOptions.setImageHandler(new HTMLServerImageHandler()); htmlOptions.setBaseImageURL(request.getContextPath()+"/images"); htmlOptions.setImageDirectory(sc.getRealPath("/images")); runAndRenderTask.setRenderOption(htmlOptions); }else if( format.equalsIgnoreCase("pdf") ){ PDFRenderOption pdfOptions = new PDFRenderOption( options ); pdfOptions.setOutputFormat("pdf"); pdfOptions.setOption(IPDFRenderOption.PAGE_OVERFLOW, IPDFRenderOption.FIT_TO_PAGE_SIZE); pdfOptions.setOutputStream(response.getOutputStream()); runAndRenderTask.setRenderOption(pdfOptions); }else{ String att ="download."+format; String uReportName = reportName.toUpperCase(); if( uReportName.endsWith(".RPTDESIGN") ){ att = uReportName.replace(".RPTDESIGN", "."+format); } response.setHeader( "Content-Disposition", "attachment; filename=\"" + att + "\"" ); options.setOutputStream(response.getOutputStream()); options.setOutputFormat(format); runAndRenderTask.setRenderOption(options); } runAndRenderTask.getAppContext().put( EngineConstants.APPCONTEXT_BIRT_VIEWER_HTTPSERVET_REQUEST, request ); runAndRenderTask.run(); runAndRenderTask.close(); } public void setBirtEngine(IReportEngine birtEngine) { this.birtEngine = birtEngine; } . .
要设置 Spring MVC(并在我们的应用程序中使用此新 View),我们需要创建一个带有 @EnableWebMVC 注解的 Spring @Configuration 类。要覆盖 Spring MVC 机制的一部分,我们可以简单地扩展一个基类 - WebMvcConfigurerAdapter - 并钩入适当的回调方法。这个类是一个常规的 Spring @Configuration 类,就像我们之前配置服务时看到的那样。我们使用 @ComponentScan 注解来告诉 Spring 将来自我们两个包的带注解的 bean 注册到 Spring context。接下来,我们覆盖 addViewControllers 方法,告诉 Spring 将以“/reports”结尾的 URL 委托给新的 Birt Spring MVC View。birtView 和 BIRT 引擎被创建为 bean,并且设置了 BirtView bean 的 birtEngine 属性。
package org.eclipse.birt.spring.example; import org.eclipse.birt.spring.core.BirtEngineFactory; import org.eclipse.birt.spring.core.BirtView; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.BeanNameViewResolver; @EnableWebMvc @ComponentScan( {"org.eclipse.birt.spring.core", "org.eclipse.birt.spring.example"}) @Configuration public class BirtWebConfiguration extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/reports").setViewName("birtView"); } @Bean public BirtView birtView(){ BirtView bv = new BirtView(); bv.setBirtEngine( this.engine().getObject() ); return bv; } @Bean public BeanNameViewResolver beanNameResolver(){ BeanNameViewResolver br = new BeanNameViewResolver() ; return br; } @Bean protected BirtEngineFactory engine(){ BirtEngineFactory factory = new BirtEngineFactory() ; //Enable BIRT Engine Logging //factory.setLogLevel( Level.FINEST); //factory.setLogDirectory( new FileSystemResource("c:/temp")); return factory ; } }
如前所述,在描述 BIRT 引擎工厂类时,我们从 BIRT 上下文提供了对 Spring ApplicationContext 的引用。BIRT 上下文对象不过是一个对象的 Map,BIRT 引擎将其提供给下游进程,例如 BIRT 表达式、BIRT 事件处理程序等。BIRT 使用 Rhino JavaScript 引擎来处理 BIRT 表达式并评估 JavaScript 事件处理程序。BIRT 上下文与 Rhino 引擎对象一起预加载到脚本环境中。这个对象允许报表开发人员使用以下语法检索 Spring Bean 并在表达式或事件脚本中使用它:
var mypojo = spring.getBean("carService"); mypojo.getAllCars() ().get(0);
如果您不想将 Spring 上下文注入 BIRT 应用程序上下文,您总是可以使用类似于以下代码的 JavaScript 来访问 BIRT 表达式和 JavaScript 事件处理程序中的 Spring bean:
importPackage(Packages.org.springframework.context); importPackage(Packages.org.springframework.web.context.support ); //ServletContext var sc = reportContext.getHttpServletRequest().getSession().getServletContext(); //ApplicationContext var spring = WebApplicationContextUtils.getWebApplicationContext(sc); var mypojo = spring.getBean("carService"); this.text = mypojo.getAllCars().get(0).getMake();
要运行此 Web 应用,请将从下载的 BIRT 3.7.1 运行时(birt-runtime-3_7_1\ReportEngine\lib 目录)中的 JAR 文件添加到 Web 应用的 WEB-INF/lib 目录。您还需要在 WEB-INF/lib 中添加从 Spring Framework 下载的以下 JAR 文件:
本文附带的示例具有以下 web.xml 文件:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <servlet> <servlet-name>springandbirt</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </init-param> <init-param> <param-name>contextConfigLocation</param-name> <param-value>org.eclipse.birt.spring.example.BirtWebConfiguration</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springandbirt</servlet-name> <url-pattern>/reports</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file> index.jsp </welcome-file> </welcome-file-list> </web-app>
所有 /reports URL 都路由到 Spring DispatcherServlet。index.jsp 中有两个链接,用于运行两个报表示例。一个报表使用 BIRT Sample Derby 数据库,另一个访问 Car Service bean,如以下代码所示:
<html> <head> </head> <body> <h1>BIRT Report</h1> <p> <a href="http://localhost:8080/springandbirt/reports?ReportName=TopNPercent.rptdesign">click here to run BIRT Report</a><br> <a href="http://localhost:8080/springandbirt/reports?ReportName=SampleSpring.rptdesign">click here to run BIRT Report that calls a Spring Bean</a> </p> <%= new java.util.Date() %> </body> </html>
在许多情况下,BIRT 用户希望将 Spring IOC 容器添加到 BIRT Viewer 中。Viewer 是一个基于 AJAX 的 Java Web 应用,用于运行和渲染报表。Viewer 支持分页、目录和导出到 PDF 等其他格式。以这种方式部署时,开发人员需要访问位于 Spring 容器中的 bean 以进行报表处理。此场景实现起来非常简单。
从 BIRT 网站下载并解压 BIRT Runtime。BIRT Viewer 位于运行时下载的 WebViewerExample 目录中。要将 Viewer 部署到 Tomcat,用户只需将 WebViewerExample 目录复制到 tomcatinstall/webapps 目录即可。大多数用户会将此文件夹重命名为更合适的名称,例如 BirtViewer。BIRT 网站提供了将 Viewer 部署到其他应用服务器的更多详细信息。安装 Viewer 后,可以将 Spring ContextLoaderListener 添加到 Viewer 的 web.xml 中。为此,请将以下监听器条目添加到 web.xml 的上下文参数下方:
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
您还可以指定一个上下文参数来指向 Spring Context 类,如以下代码所示:
<context-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>org.eclipse.birt.spring.webviewer.example.BirtDataServiceConfiguration</param-value> </context-param>
在此场景中,我们不需要 BirtWebConfiguration 类,因此我们将 contextConfigLocation 指向 BirtDataServiceConfiguration 类。
本文第一节中描述的相同 POJO 类在此处使用(只是包名不同),并且需要位于 WEB-INF/classes 目录中,或者该包需要位于 JAR 文件中并放置在 Viewer 的 WEB-INF/lib 目录中。最后,将 Spring Framework 下载中的以下 JAR 文件添加到 WebViewer 的 WEB-INF/lib 目录:
要在 BIRT 表达式或 BIRT JavaScript 事件处理程序中访问 carService bean,请使用以下语法:
//BIRT label report item onCreate Script importPackage(Packages.org.springframework.context); importPackage(Packages.org.springframework.web.context.support ); var sc = reportContext.getHttpServletRequest().getSession().getServletContext(); //ApplicationContext spring = WebApplicationContextUtils.getWebApplicationContext(sc); var mypojo = spring.getBean("carService"); this.Text = mypojo.getAllCars().get(0).getMake();
在设计器中预览报表时,BIRT 表达式或脚本会失败。为防止失败,请将表达式或脚本包装在“if”语句中,如以下代码所示:
if( !reportContext.getHttpServletRequest().getAttribute("attributeBean").isDesigner()){ //Access Bean }
本文前两节侧重于将 BIRT 引擎和 Viewer 与 Spring 框架集成。虽然这些方法效果很好,但假设您需要访问位于单独上下文或另一台机器上的 Spring bean。可以使用 Spring Remoting 来实现此功能。
虽然任何 Spring Remoting 技术或其他机制,如 SOAP 或 REST 都可以使用,但本节描述了使用 Spring 基于 HTTP Invoker 的服务导出器。为了实现本示例,我们首先构建一个示例 Web 应用,其中包含一个 Car Service bean,该 bean 向远程调用客户端提供 Car POJO。
对于远程调用,我们首先定义 Car POJO,如以下代码所示:
package org.eclipse.birt.spring.remoting.example; public class Car implements ICar{ private static final long serialVersionUID = 1L; private String make; private String model; private String year; public String getMake() { return make; } public void setMake(String make) { this.make = make; } public String getModel() { return model; } public void setModel(String model) { this.model = model; } public String getYear() { return year; } public void setYear(String year) { this.year = year; } public Car() { this.year = "2000"; this.make = "Chevrolet"; this.model = "Corvette"; } public String toString(){ return "Make:--"+this.make+" Model:--"+this.model+" Year:--"+this.year; } }
接下来,我们实现 Car Service。
package org.eclipse.birt.spring.remoting.example; import java.util.Arrays; import java.util.List; import org.eclipse.birt.spring.remoting.example.Car; import org.eclipse.birt.spring.remoting.example.CarService; public class CarServiceImpl implements CarService{ public ListgetAllCars(){ Car car1 = new Car(); car1.setYear("2000"); car1.setMake("Chevrolet"); car1.setModel("Corvette"); Car car2 = new Car(); car2.setYear("2005"); car2.setMake("Dodge"); car2.setModel("Viper"); Car car3 = new Car(); car3.setYear("2002"); car3.setMake("Ford"); car3.setModel("Mustang GT"); List cars = Arrays.asList( car1, car2, car3 ) ; return cars ; } }
最后,我们实现 BirtDataServiceConfiguration 文件来处理 Spring 上下文的 Java 配置。
package org.eclipse.birt.spring.remoting.example; import java.util.HashMap; import java.util.Map; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter; import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; @Configuration public class BirtDataServiceConfiguration { @Bean public CarService carService(){ return new CarServiceImpl(); } @Bean public HttpInvokerServiceExporter myServiceExporter(){ HttpInvokerServiceExporter hse = new HttpInvokerServiceExporter(); hse.setService( this.carService()) ; hse.setServiceInterface( CarService.class); return hse; } @Bean public SimpleUrlHandlerMapping myUrlMapping(){ SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); MapurlMap = new HashMap (); urlMap.put("/carService", myServiceExporter()); mapping.setUrlMap(urlMap); mapping.setAlwaysUseFullPath(true); return mapping; } }
这个类只是将 /carService URL 映射到 HttpInvokerServiceExporter 对象,该对象将 carService bean 暴露给远程调用客户端。
接下来,我们可以为这个应用程序创建一个使用 Spring DispatcherServlet 的 web.xml 文件,如以下代码所示:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <servletgt; <servlet-name>springandbirt</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-namegt;contextClass</param-name> <param-valuegt;org.springframework.web.context.support.AnnotationConfigWebApplicationContextlt;/param-value> </init-param> <init-param> <param-name>contextConfigLocation</param-name> <param-value>org.eclipse.birt.spring.remoting.example.BirtDataServiceConfiguration</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springandbirt</servlet-name> <url-pattern>/carService</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file> index.jsp </welcome-file> </welcome-file-list> </web-app>
该 Web 应用程序需要在 WEB-INF/lib 目录中包含 Spring Framework 的以下 JAR 文件:
现在可以构建和部署该应用程序了。
接下来,我们需要构建一个远程调用客户端来访问之前构建的应用程序。在此示例中,它只是一个 JAR 文件,我们可以将其包含在 BIRT Viewer 中,以便在单独的上下文访问 carService。
客户端 JAR 文件应该包含 CarService 接口和 CarPojo/ICarPojo 类/接口。除了这三个类之外,我们还需要一个配置类来处理 Spring Context 的 Java 配置。
此类使用 AnnotationConfigApplicationContext 类指定一个 Java 类来处理 Spring Context 的配置。ContextConfig 类如下所示,并使用 HttpInvokerProxyFactoryBean 连接到服务器并检索 car service bean。
package org.eclipse.birt.spring.remoting.client.example; import org.eclipse.birt.spring.remoting.example.CarService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean; @Configuration public class ContextConfig { @Bean public HttpInvokerProxyFactoryBean client() { HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean(); proxy.setServiceInterface(CarService.class); proxy.setServiceUrl("http://localhost:8080/springandbirtremote/carService"); return proxy; } }
这个配置文件定义了一个 bean,它充当 HTTP invoker 代理。服务 URL 定义了我们之前定义的远程调用服务器的位置,服务接口定义了返回的对象。要构建客户端 JAR 文件,将为服务器添加的相同 JAR 文件添加到 classpath。
要从 BIRT 查看器调用 car service,请在 BIRT Expression Builder 或 JavaScript 事件处理程序中使用以下 JavaScript 代码片段,如以下代码所示:
importPackage(Packages.org.springframework.context); importPackage(Packages.org.springframework.web.context.support ); var sc = reportContext.getHttpServletRequest().getSession().getServletContext(); //ApplicationContext var spring = WebApplicationContextUtils.getWebApplicationContext(sc); var mypojo = spring.getBean("client"); mypojo.getAllCars().get(0).getMake();
将构建远程调用服务器一节中描述的所有 JAR 文件添加到 BIRT Viewer 的 WEB-INF/lib 目录。此外,将远程调用客户端 JAR 文件添加到 BIRT Viewer 的 WEB-INF/lib 目录。最后,将以下内容添加到已部署 Viewer 的 web.xml 中。这些设置在本文“从 BIRT Viewer 访问 Spring Bean”一节中进行了讨论。请注意,contextConfigLocation 已更改为 ContextConfig 类。
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>org.eclipse.birt.spring.webviewer.example.ContextConfig</param-value> </context-param>
这种方法允许已部署的 BIRT Viewer 访问单独的机器/上下文来访问远程 bean。最后,如果您使用中间 Java 类来访问远程 Bean,请使用以下代码。
. . private final CarService carPojoService; public CarPojoClient(){ final ApplicationContext context = new AnnotationConfigApplicationContext( ContextConfig.class); this.carPojoService = (CarService) context.getBean("client"); . .
Spring 和 BIRT 框架在 Java 社区中非常流行。许多 BIRT 技术的用户也在其企业应用程序代码中使用 Spring 功能来处理数据源、报表呈现和访问控制等功能。这些只是将 Spring Framework 与 BIRT 结合使用的一些好处。本文介绍了如何集成 BIRT 和 Spring。虽然还存在其他场景,但本文可以作为入门工具,帮助您同时使用这两种技术。
希望利用本文所述集成类的开发人员可以使用下面的 SpringandBirtCoreJar.zip
下载。对于示例,请参阅 SpringBirtArticleSamples.zip
下载。