WEB开发网
开发学院软件开发Java 基于 Eclipse 的 Birt 国际化的分析与改进 阅读

基于 Eclipse 的 Birt 国际化的分析与改进

 2010-03-30 00:00:00 来源:WEB开发网   
核心提示:开发环境本文的开发环境为 Windows Vista Enterprise、birt-report-designer-all-in-one-2_2_2、Birt 2.2.2、Java EE 服务器使用 apache-tomcat-6.0.18,当然,基于 Eclipse 的 Birt 国际化的分析与改进,您也可以使用

开发环境

本文的开发环境为 Windows Vista Enterprise、birt-report-designer-all-in-one-2_2_2、Birt 2.2.2、Java EE 服务器使用 apache-tomcat-6.0.18,当然,您也可以使用 Jboss 等其他 Java EE 服务器。

初识 BIRT

BIRT 是一个 Eclipse-based 开放源代码报表系统同 JasperReports 类似。它主要是用在基于 Java 与 J2EE 的 Web 应用程序上。BIRT 主要由两部分组成:一个是基于 Eclipse 的报表设计和一个可以加到你应用服务的运行期组件。BIRT 同时也提供一个图形报表制作引擎。

BIRT 报表文件的国际化

新建 birt 报表的过程请参考网站的其他文档,现有一个名为 internationalization_file.rptdesign 报表文件,然后在 layout 视图点击报表的空白处如下所示:注意一定是空白处,点击其他位置是不能出现这个菜单项的。

图 1. 选择报表的资源文件
基于 Eclipse 的 Birt 国际化的分析与改进

然后点选 resources 标签页,点击 Add 按钮来加入资源文件或者输入资源文件名称。

注意:如果在属性 Resources 中填写了 MyResources, 那么资源文件的名称要以以下规律命名:

MyResources_en_US.properties、 MyResources_zh.properties 等,资源文件定义符合 Java I18N 格式。后面的 _en_US 或 _zh d 等由参数 __locale 传递。那么资源文件要放到哪里呢?我们通过在应用的 web.xml 中定义 <param-name>BIRT_RESOURCE_PATH</param-name> 来确定资源文件的位置,这也是指定报表文件路径的参数。

报表文件国际化的实例演示

现在我们指定了 internationalization_file.rptdesign 报表文件的 Resources 为 MyResources,并建立两个 property 文件,一个中文资源文件 MyResources_zh.properties, 另一个为英文资源文件 MyResources_en_US.properties,资源文件内容如下:

MyResources_zh.properties:name=\u663E\u793A\u53D8\u91CF

MyResources_en_US.properties:name=show param

将报表文件的字段指定为资源文件中定义的键值。

图 2. 指定对应的键值
基于 Eclipse 的 Birt 国际化的分析与改进

然后将报表文件及所需的资源文件放到服务器对应的目录下,如:\webapps\WebViewerExample。在浏览器中输入 http://localhost:8080/WebViewerExample/frameset?__report=internationalization_file.rptdesign&sample=my+parameter&__locale=en_US显示如下:

图 3. 资源文件为英文的
基于 Eclipse 的 Birt 国际化的分析与改进

然后将上面的 URL 中的 __locale=en_US 换成 __locale=zh, 显示如下:

图 4. 资源文件为中文的
基于 Eclipse 的 Birt 国际化的分析与改进

BIRT-console 的国际化

通常情况下,我们还是用 birt 提供的 console 来展示报表的,如果 console 提供的功能不能满足我们的要求,在上面做二次开发也是挺简单的事情,如果重新再开发一个 birt 报表的展示 console,造同样轮子的做法不是很值得提倡的。回到正题上来,我们怎样国际化 birt-console 呢?国际化文件放到哪里?是否可以将国际化文件移到一个可管理的路径下呢?接下来,我们会一一解开这些疑惑。

Birt 提供了国际化 console 的方法,国际化文件放在一个名为 viewservlets.jar 包里面,名称为 Messages.properties。如果我们要实现中文的国际化,是否放入一个中文的资源文件就可以呢?实践往往是验证疑惑最有效的方法,实际结果验证这样是不行的。下面我们来看一下 birt 实现 console 国际化部分的代码,类 BirtResources 调用的是 ViewerResourceHandle 类。

清单 1. BirtResources 类

 public static String getMessage( String key ) 
 { 
  ViewerResourceHandle resourceHandle = getResourceHandle( ); 
  if ( resourceHandle != null ) 
  return resourceHandle.getMessage( key ); 
 
  return key; 
 } 

类 ViewerResourceHandle 继承自 ResourceHandle 类。

清单 2. ViewerResourceHandle 类

 public class ViewerResourceHandle extends ResourceHandle 

我们再看 ResourceHandle 类,这个类是组织资源文件的关键类:

清单 3. ResourceHandle 类

 public ResourceHandle( ULocale locale ) 
  { 
  String className = this.getClass( ).getName( ); 
  String bundleName = ""; //$NON-NLS-1$ 
 // Create the base message file name formatted like a Java class. 
 // The Java class loader will search for the file using the same 
 // algorithm used to find classes. 
   int index = className.lastIndexOf( '.' ); 
   if ( index > -1 ) 
   { 
 // e.g: "org.eclipse.birt.report.model.util.Test" 
 bundleName = className.substring( 0, index ) + "."; 
 //$NON-NLS-1$ 
   } 
 
   bundleName = bundleName + BUNDLE_NAME; 
   if ( locale == null ) 
    locale = ULocale.getDefault( ); 
   resources = UResourceBundle.getBundleInstance( 
        bundleName, locale.toString(), this.getClass().getClassLoader() ); 
 assert resources != 
     null : "ResourceBundle : " + BUNDLE_NAME + " for " + locale + " not found"; 
 //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ 
 } 

从 this.getClass().getClassLoader()可以看出来 console 的国际化文件是放在类路径下面的,文件的组织形式是文件名称 +locale,再有资源文件放到 jar 包里面类路径下可不是什么好的方法,那么我们是否能提供一个外部变量来配置这个资源文件的路径呢?后面我们会讲到。先来看看为什么中文资源文件放到 jar 包里面的类路径下不起作用,明明是有 locale 的,是不是感觉有点奇怪?我们接下来继续跟踪,进入类 ReportEngineService 中的方法 createGetParameterDefinitionTask, 看它的方法体:

清单 4. 原 createGetParameterDefinitionTask 方法

 public IGetParameterDefinitionTask createGetParameterDefinitionTask( 
    IReportRunnable runnable, InputOptions options ) 
  { 
   IGetParameterDefinitionTask task = null; 
 
   try 
   { 
 HttpServletRequest request = 
      (HttpServletRequest) options.getOption( InputOptions.OPT_REQUEST ); 
 
    task =    engine.createGetParameterDefinitionTask( runnable );     
    // set app context 
  Map context = BirtUtility.getAppContext( request,  
             ReportEngineService.class.getClassLoader( ) ); 
    task.setAppContext( context ); 
   } 
   catch ( Exception e ) 
   { 
   } 
 
   return task; 
  } 

我们会注意到服务层的这个入口方法中没有设置任何与 locale 相关的变量,添加设置 locale 变量的代码,修改后的 createGetParameterDefinitionTask 如下所示:

清单 5. 修改后的 createGetParameterDefinitionTask

 public IGetParameterDefinitionTask createGetParameterDefinitionTask( 
    IReportRunnable runnable, InputOptions options ) 
  { 
   IGetParameterDefinitionTask task = null; 
 
   try 
   { 
 HttpServletRequest request = 
   (HttpServletRequest) options.getOption( InputOptions.OPT_REQUEST ); 
 
    task = engine.createGetParameterDefinitionTask( runnable ); 
 task.setLocale(ParameterAccessor.getLocale(request));  
    // set app context 
  Map context = BirtUtility.getAppContext( request, 
       ReportEngineService.class.getClassLoader( ) ); 
    task.setAppContext( context ); 
   } 
   catch ( Exception e ) 
   { 
   } 
 
   return task; 
  } 

类 ParameterAccessor 感兴趣的朋友可以研究一下,他是传递入口参数的。如 __action、__nocache、__report 等,参数说明如下。

表 1. 参数描述

参数名 参数说明 参数值 默认值
__format 指定报表输出格式 html 或 pdf html
__isnull 指明一个参数是 null,常用于字符串类型。如果提供参数且值为空: - 对于日期和数字类型,BIRT 会将它们当作 null 处理。 - 对于字符串,BIRT 会将它作为空字符串。因此,为了说明某个字符串是 null,通常写为:__isnull= 参数。 报表输入参数名 None. Required.
__locale 本地化选项 en-us 或 ch-zh 虚拟机默认
__report 指定 *.rptdesign 文件路径   None. Required.
__svg 指定是否使用 SVG 矢量图来显示图表。
SVG 矢量图形是一种 XML 格式的文本文件,在 IE 下需要安装 Adodb SVG Viewer 插件才能浏览。
true 或 false 安装插件后浏览时
frameset 下默认 true,run 下默认 false;不安装插件时默认为 false

管理 console 国际化的资源文件

通过上面讲解,我们知道 ViewerResourceHandle 继承自 ResourceHandle 类,而 ResourceHandle 类是负责组织资源文件的,代码默认是将资源文件放到类路径下的,也就是该类的包路径下。通过以上分析可知,如果我们想改变资源文件的路径只能有这么两种方法。方法一,重写一个 ResourceHandleNew 类 , 然后让 ViewerResourceHandle 继承自 ResourceHandleNew; 方法二,修改 public ResourceHandle( ULocale locale ) 方法,或添加一个新的方法 public ResourceHandleExtent( ULocale locale ),在 ResourceHandleExtent 方法中实现资源文件路径可以通过外部变量来配置。其实两种方法各有千秋,不过核心就是都要修改 ResourceHandle 方法来达到管理资源文件的目的。下面我们来重写 ResourceHandle 方法。

清单 6. 修改后的 ResourceHandle

 public ResourceHandle( ULocale locale ) 
  { 
   if ( locale == null ) 
    locale = ULocale.getDefault( ); 
   // get resource path 
   String birtResourceFolder = ParameterAccessor.processRealPath( context, 
   context.getInitParameter( INIT_PARAM_BIRT_RESOURCE_PATH ), null, false ); 
   // 这个地方是需要完善的 
   String bundleName = birtResourceFolder+"/" + BUNDLE_NAME 
            +"_"+locale.getLanguage()+"_"+locale.getCountry(); 
    Reader reader = null; 
    try { 
      reader = new FileReader(bundleName); 
      resource = new PropertyResourceBundle(reader);      
    } catch (FileNotFoundException ex) { 
      ex.printStackTrace(); 
    } catch (IOException ex) { 
      ex.printStackTrace(); 
    } finally { 
      if (reader != null) { 
        try { 
          reader.close(); 
        } catch (IOException ex) { 
          ex.printStackTrace(); 
        } 
      } 
    }     
  } 

INIT_PARAM_BIRT_RESOURCE_PATH 这个参数是不是有点熟悉,就是配置报表文件路径的变量,是 web.xml 中定义的 <param-name>BIRT_RESOURCE_PATH</param-name> 这个变量的值。至此我们完全可以将 console 的资源文件放到 jar 外面来进行管理了。

经常遇到的一些 birt 相关问题的总结

Birt view 界面显示红叉如:

图 5. 经常遇到的问题之一
基于 Eclipse 的 Birt 国际化的分析与改进

解决方法:

viewer.properties 文件的 #base_url=http://127.0.0.1:8080

设置不对,该设置主要应用于代理服务器的情况下,在使用代理服务器后,从 request 里获取的 URI 并非真正的 URI,需要在这里设置。

控制 birt 日志输出级别

解决方法:

在 web.xml 中设置

  <context-param> 
   <description> 
   Report engine log level.( ALL|SEVERE|WARNING|INFO|CONFIG|FINE|FINER|FINEST|OFF ) 
   </description> 
   <param-name>BIRT_VIEWER_LOG_LEVEL</param-name> 
   <param-value>ALL</param-value> 
  </context-param> 

访问 http://[yourip]:[yourport]/WebViewerExample/ 然后点击 View Example 后出现异常

解决方法:

将 common-logging.jar 包添加到 birt-runtime-2_2_2\WebViewerExample\WEB-INF\lib 目录下。

说明:本文相关代码的修改只为提供给开源爱好者研究代码使用,如用于商业用途责任自负。

总结

文章主要讲解了如何国际化 birt 的报表文件及 birt 提供的 console 界面,由于 birt 代码本身的一些局限性,使得 birt console 的国际化文件管理起来有些问题,通过修改相关代码来达到灵活管理 console 资源文件的目的,通过跟踪相关类间关系,有助于我们更好的了解 birt 国际化的实现方式。

Tags:基于 Eclipse Birt

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接