Eclipse rap 开发经验总结

 原文地址:http://www.360doc.com/content/12/0521/15/1332348_212538068.shtml

一rap简单介绍 
1 基本概念 
    RAP可以让开发人员使用JAVA API和按照Eclipse 插件的开发模式构建基于AJAX的Web 2.0应用程序, RAP的工作原理是采用交叉编译的方式将Java 代码生成html、JavaScript和CSS文件,底层基于Qooxdoo AJAX框架,这样,我们就不必接触JavaScript、CSS和处理Http的细节了,可以让我们更关心程序的功能实现。 
2 与rcp的关系  
    RAP和RCP 一样,运行在Equinox框架上,Equinox是OSGI R4规范的实现,是一个非常优秀和成熟的OSGi框架,Eclipse 是通过这个框架实现灵活的扩展性和插件的热部署。RAP也支持Eclipse的大部分扩展点,其实RAP和RCP在架构上非常的类似,下图分别为RCP和RAP的架构图 
  


可以看出,这之间的整体架构差别不大,RCP是基于SWT的,RAP是基于RWT的,RWT是实现了SWT功能的一个子集。其实这之间的使用方式都差不多。比如RWT也能和SWT一样使用MVC的方式来创建表格。 

     简单的说就是让RCP的程序在浏览器中展示,那什么是RCP呢?RCP就是由eclipse 插件开发转向桌面应用开发,让你开发出来和eclipse一样的程序一样构造的程序出来,复用eclipse的视图、编辑器、状态栏等等,摆脱失败的awt和swing,让程序拥有专业级效果,程序实现又很简单很优雅,试想一下哪天eclipse整体的界面都可以跑在web上面?对,rap就可以实现,而且eclipse 官方也计划E4版本上让eclispe在web上面跑?虽然现在的进度有很大的延迟,但是我们可以看到rap的版本还是在有条不紊的发布,让eclipse跑在浏览器上面也不会太远了吧。 

3 最新版本下载 
  1、下载eclipse rcp/rap版本      Eclipse for RCP and RAP Developers 
       http://www.eclipse.org/downloads/packages/eclipse-rcp-and-rap-developers/indigosr1 
   安装方式1 
    在eclipse中打开Help?Welcom?Overview选项,选择Rich Ajax Platform?   Install Target Platform,如下图 



点击ok即可完成安装。 
3.2 安装方式2 
   选择Help?Install New Software,选择如下图所示的网址,选择rap选项,如下图所示;点击Next然后Finish即可完成安装。 
如果下拉选项中没有下图所示的网址,可以点击右侧的Add按钮进行添加。 


 

4 相关文档 
http://help.eclipse.org/indigo/index.jsp?topic=/org.eclipse.rap.help/help/html/intro.html 

1、 Eclipse rap项目目前的进度


   目前rap 的最新版本是 rap 1.5M4,最稳定版本是 rap 1.4.1,我们项目目前使用的版本是rap 1.4.1,Rap目前已经支持的部分是 swt,JFace,rap目前暂时不支持的部分是 dwaw2d、gef关于对dwaw2d、gef的支持目前正在开发中,原计划在eclipse E4版本中支持,目前改版本已经延迟了,而且暂时不支持dwaw2d、gef,至于什么时候完成,就不得而知了. 
关于版本和支持情况大家可以去这个页面上看一下 
http://www.eclipse.org/rap/downloads/ 

2、目前rap上存在的问题   


   1、运行速度

       速度上面不同浏览器支持情况不同,使用chrome浏览器速度最快,firefox其次,IE浏览器(所有IE核心的都一样)最慢,而且不支持IE6(IE6上面跑界面上显示有些小问题),其他浏览器没有试过.大家有时间可以验证下,目前官方上发布支持的浏览器有 
Firefox 2+ 、IE 7+ 、Safari 3+ 、Chrome 3+ 、Opera 9+


   2、系统的bug 


       现在稳定版本的bug不少,开发中遇到的问题也不少,例如  treeViewer 会出现遮挡,系统自带的提示框第一次弹出的时候只能展示一半,等等,当然这些bug都可以通过其他的方式给避免掉.  

郑重提示:想在自己项目中使用rap朋友们一定要慎重考虑 
   是否有精力和人力来处理一下”小”问题 

虽然rap 是rcp的web版本,但是因为 一个是图形界面,一个是web界面,它们之间还是存在一些差异,现在把我们项目中碰见的差异罗列一下,大家以后碰见了就不至于浪费时间找原因了.^_^

 

1、 Label和Button按钮的显示的差异

    当Label 和 Button显示的文字过长显示不开的时候,rcp、rap的处理方式就不一样了,rap显示不开会自己截取掉后面的文字,rcp会在文字的中间加上省略号.

还有关于Label 和Button 设置图片,文字过长的时候rap的图片不会显示,可以使用CLabel来替换Label

建议统一处理方式:不使用他们自带的文字截取方式,统一计算文件的长度,在文字最后面加上… 来使二者统一

2、 TreeViewer的差异

     目前最新的rap 版本 TreeViewer偶尔有遮挡的问题,这个问题暂时不能有效的避免,

3、 属性视图 -tree无法设置行高的问题

     关于设置 treeViewer的高度,rcp支持设置行的高度,rap不支持,这个暂时没有解决方法

4、 对GEF、draw2d的支持

     目前rap暂时不支持GEF draw2d,不过目前已经在开发中。

5、 paint监听,rap没有

        rap组建很多都没有paint 重绘方法,导致很多界面不能进行重绘。比如treeVIewer上面添加cellEditor进行界面上直接编辑,因为不支持,paint 导致 cellEditor和当前的行的位置不匹配。在后续文章中会对此问题的解决方法进行专门的讲解

6、 扩展点的差异控制台扩展点

       Rap界面目前对扩展点的支持也不是很完善,控制台扩展点和帮助视图扩展点都不是很完善,不过大家可以自己实现.不是很复杂

7、 帮助系统的差异

         Rcp /rap的帮助系统完全不同,rap的帮助系统只是加载一个jsp页面

         8、上传下载的差异

          一个是web 一个是图形界面,后续会写如何在rap实现上传和下载

         9、视图拖动

                   用过eclipse的朋友都知道,eclipse之间的视图是可以任意拖动的,目前Rap不支持,视图间的拖动,这个算是比较遗憾吧


完成后:


 

最后点finish。

 

重新打开RAP程序,可以看到汉化结果。


1、  在工程的根目录下面建立一个plugin.properties资源文件;在此资源文件中写入需要国际化的内容(键/值对),举例如下:

Java代码   收藏代码
  1. helloWorldView_name=eclipse国际化  
  2. helloWorldView_city=北京  
  3. ...  

 2、 

在 MANIFEST.MF文件中增加代码行:Bundle-Localization: plugin;

说明:添加代码行中的plugin这个名称是plugin.properties 这个文件的名称。也可以是其它的名称但要与文件名保持一致。

3、  plugin.xml配置文件对资源文件进行引用时, 在引用的key前面加一个%即可;

plugin.xml引用资源文件举例如下:

Xml代码   收藏代码
  1. <extension  point="org.eclipse.ui.views">    
  2.   
  3. <view    
  4.   
  5.       id="org.eclipse.rap.helloworld.helloWorldView"    
  6.   
  7.  class="org.eclipse.rap.helloworld.HelloWorldView"    
  8.   
  9.  name="%helloWorldView_name">    
  10.   
  11. </view>    
  12.   
  13.  </extension>    

 

 

 

类文件中中文内容的国际化

1、  建立一个messages_zh_CN.properties资源文件;

说明:此资源文件中的内容为需要国际化的键/值对;

2、  建立一个Messages.java类文件,文件内容如下:

Java代码   收藏代码
  1. import org.eclipse.osgi.util.NLS;  
  2.   
  3.    
  4.   
  5. public class Messages extends NLS  
  6.   
  7. {  
  8.   
  9.      private static final String BUNDLE_NAME = "telecomui.nls.messages";   
  10.   
  11. public static String PriceDomainDao_AddTextToBrower;  
  12.   
  13. static {  
  14.   
  15.             NLS.initializeMessages(BUNDLE_NAME, Messages.class);  
  16.   
  17.         }  
  18.   
  19.         private Messages(){  
  20.   
  21.         }  
  22. }  

 

 

3、  在需要进行国际化的类文件上点击右键,出现下图的操作:



 

4、  点击蓝色菜单选项后,弹出下面的窗体,如图:


5、  在上图中列出的需要国际化的字段中,对需要进行国际化的字段前勾选加号,不需要进行国际化的字段前勾选差号;

注意:

对于需要进行国际化的字段项,如图


 

中字段Test_0是生成到资源文件中的默认key值,建议进行重命名下,建议命名规则是最好以当前类名做前缀;如上字段可命名为:Test_printStr;

6、  单击窗体中的【Configure…】按钮,弹出窗体,如图:


 

 

7、  对上图中的各选项进行设置后,点击【ok】按钮—>【next】—>【finish】

 先下载以来的打包插件

war products


 
 输入下面的地址,选择相应的插件


新建一个 war product Configutation向导

 下面的war  product Configutation 配置面板

选择插件

 

将除了 自己项目 在外的所有插件都删除,然后点 Add Required Plug-ins 将需要的插件添加进来,吧所有的关于 Jetty 和Juit 的插件全部删除掉,这样在验证的时候就不会出现什么错误。避免把没必要的插件加进来。

 

在 Overview 中点 Validate 按钮验证是否存在问题:



 点击导出war

 发布成功

1、 Rap样式原理

 

Rap的界面样式目前是以css来配置的,程序启动后加载相应的css配置文件再对组件进行样式设置,界面上的所有组件Label button composit等的样式最开始都是通过css来确定显示样式的.因此只需要选择不同的css文件就可以控制css样式了

 

2、 Rap如何选择样式

 

Plugin.xml – 扩展 – 新建 org.eclipse.rap.ui.branding 扩展点 – 在这个扩展点上新建branding .在 branding上就可以选择样式了,对应的选项是themdID ,点击浏览就可以选择目前已经存在的样式

目前rap自带的样式大约有2个 , Classis 样式和 Default ,

建议大家使用Classis 样式,因为默认的default样式本身在界面显示上面会有不少的问题.

 

3、 修改rap自带的样式

 

如果你觉得目前rap界面上的样式不太符合你的要求,那么你就可以新建自己的rap样式 方法如下:

新建扩展点:org.eclipse.rap.ui.themes

在扩展点上新建 theme

点击 theme 会有一个属性 file,这个是用来选择对应的样式css文件的.

关于rap每个组建对应的样式名称,大家可以通过如下方式进行查看

找到 org.eclipse.rap.rwt.theme.classes 插件(直接通过插件列表-导出源代码到目前工程)

在对应的 theme目录下面就可以看到 classic.css文件了

 

4、 Rap样式的发布

 

Rap最好按照默认的方式以插件的形式进行发布,这样就可以松耦合了.

1 、解决 rap 字符集乱码的问题

    字符集问题,解决办法:   在plugin.xml - build.properties 中添加

      javacDefaultEncoding.. = UTF-8   即可解决字符集乱码


2、解决web前台输入乱码问题

    使用传统的 字符集过滤器


    写一个过滤器类

 

 

Java代码   收藏代码
  1. <span style="font-size: small;">public class CharacterEncodingFilter implements Filter  
  2. {  
  3.   private String edcoding;  
  4.   
  5.   private FilterConfig filterConfig;  
  6.   
  7.   private boolean ignore;  
  8.   
  9.   public CharacterEncodingFilter()  
  10.   
  11.   {  
  12.     this.edcoding = null;  
  13.   
  14.     this.filterConfig = null;  
  15.   
  16.     this.ignore = true; }  
  17.   public void destroy() {  
  18.   
  19.     this.edcoding = null;  
  20.   
  21.     this.filterConfig = null;  
  22.   
  23.   }  
  24.   
  25.   public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException  
  26.   
  27.   {  
  28.   
  29.     if ((this.ignore) || (request.getCharacterEncoding() == null)) {  
  30.   
  31.       String encoding = setCharacterEncoding(request);  
  32.       if (encoding != null)  
  33.   
  34.         request.setCharacterEncoding(encoding)  
  35.   
  36.     }  
  37.   
  38.   
  39.     filterChain.doFilter(request, response);  
  40.   
  41.   }  
  42.   
  43.   
  44.   
  45.   public void init(FilterConfig filterConfig) throws ServletException {  
  46.     this.filterConfig = filterConfig;  
  47.     this.edcoding = filterConfig.getInitParameter("encoding");  
  48.     String value = filterConfig.getInitParameter("ignore");  
  49.   
  50.     if (value == null)  
  51.       this.ignore = true;  
  52.     else if (value.equalsIgnoreCase("true")) {  
  53.       this.ignore = true;  
  54.     }  
  55.     else  
  56.       this.ignore = false;  
  57.   }  
  58.   public String setCharacterEncoding(ServletRequest request)  
  59.   
  60.   {  
  61.   
  62.     return this.edcoding;  
  63.   
  64.   }  
  65.   
  66. }  
  67.   
  68. </span>  

 

 

 

 

 

然后达成 jar 包方式到 war /WEB_INF/lib 目录下面

在 web.xml 添加

 

 

 

rap 导出 war 包时,编码问题处理,加入了字符过滤器的处理方式

1. 在导出 WAR 后,修改 war 包里面的 web.xml 文件,添加过滤器,


 

内容如下


 

Java代码   收藏代码
  1. <span style="font-size: small;"><span>  <filter>    
  2.   
  3.         <filter-name>CharacterEncodingFilter</filter-name>    
  4.   
  5.         <filter-class>com.encoding.CharacterEncodingFilter</filter-class>    
  6.   
  7.         <init-param>    
  8.   
  9.             <param-name>encoding</param-name>    
  10.   
  11.             <param-value>UTF-8</param-value>    
  12.   
  13.         </init-param>    
  14.   
  15.     </filter>    
  16.   
  17.     <filter-mapping>    
  18.   
  19.         <filter-name>CharacterEncodingFilter</filter-name>    
  20.   
  21.         <url-pattern>/*</url-pattern>    
  22.   
  23. </filter-mapping>  
  24.   
  25. </span>  
  26.   
  27. </span>  

 

 

 

2. 增加 jar 包

   把过滤器要用的 jar 包【 encoding.jar 】添加到导出的 WAR 包的 lib 下面,这样     WAR 包加载后,能够找寻到过滤器用到的类。

 

 

 

上面 2 部分可以保证完美的解决中文问题

一 上传

上传即将文件上传到服务器上,在客户端需要写相应的脚本,服务器端需要注册相应的 handle 接受客户端的请求。

原理:

  Rap 的上传和下载是通过普通的 web 的方式进行上传和下载的 , 但是和传统的 wen 还不相同

1、  rap 本身就单线程在跑 , 和上传下载的线程不能进行混淆

所以采用的方式如下:

上传:通过传统的方式上传到指定目录 ,rap 不能直接操作上传的文件流 , 如果想获得上传的数据必须要先上传到指定文件 , 然后让 rap 去加载指定文件即可

下载: 先通过 rap 程序生成需要下载的文件到指定目录 , 然后通过 rap 加载成文件流的形式发送给客户端

 

1 在服务器端注册相应的 handler

  // 注册上传处理事件

  IServiceManager manager = RWT.getServiceManager ();

  IServiceHandler uploadHandler = new UploadServiceHandler();

manager.registerServiceHandler( "uploadServiceHandler" , uploadHandler); //$NON-NLS-1$

 

2 在客户端的脚本调用

目前的做法是创建上传的 dialog, 在 dialog 里面添加 browser 控件,然后 browser 里书写上传的 javaScript 脚本,脚本请求的 url 格式可以通过以下类似的代码创建:

   private String createUploadUrl(String uploadFileName) {

      StringBuffer url = new StringBuffer();

      url.append(RWT.getRequest ().getContextPath());

      url.append(RWT.getRequest ().getServletPath());

      url.append( "?" ); //$NON-NLS-1$

      url.append(IServiceHandler . REQUEST_PARAM );

      url.append( "=uploadServiceHandler" ); //$NON-NLS-1$

      url.append( "&fileName=" ); //$NON-NLS-1$

      url.append(uploadFileName);

      return url.toString();

   }

3 服务器端 handler 的写法

public class UploadServiceHandler implements IServiceHandler {

   public void service() throws IOException, ServletException {

      HttpServletRequest request = RWT.getRequest ();

      request.setCharacterEncoding( "UTF-8" );

      String fileName = request.getParameter( "fileName" );

      FileOutputStream o = null ;

      BufferedReader bufferReader = null ;

      InputStream in = null ;

      try {

         in = request.getInputStream();

         File f = null ;

         try {

          f = new File(FileUtil.getTempFilePathAndName (RWT.getRequest ()

            .getSession().getAttribute( "userName" ).toString(),

                   fileName));

         } catch (Exception e) {

            throw new IOException(e);

         }

         o = new FileOutputStream(f);

         bufferReader = new BufferedReader( new InputStreamReader(in));

         String line = null ;

         boolean beginWrite = false ;

         boolean endWrite = false ;

         while ((line = bufferReader.readLine()) != null ) {

            if (line.indexOf(PriceDomainBean. class .getName()) != -1) {

                if (!beginWrite) {

                   beginWrite = true ;

                } else {

                   endWrite = true ;

                }

            }

            if (beginWrite) {

                o.write((line + "\r\n" ).getBytes());

            }

            if (endWrite) {

                break ;

            }

         }

      } catch (IOException e) {

         throw e;

      } finally {

         if null != o) {

            o.close();

         }

         in.close();

         if null != bufferReader) {

            bufferReader.close();

         }

      }

      HttpServletResponse response = RWT.getResponse ();

      response.setContentType( "text/html;charset=UTF-8" );

      response.getWriter().write(

            "<br><br><br><DIV align=center><h2> 上传成功 !</h2>" );

   }

}

二 下载

下载和上传采用的方式基本相同,只不过是将服务器文件读取到本地,和上传是一个相反的过程。

1 在服务器端注册相应的 handler

  // 注册下载处理事件

  IServiceManager manager = RWT.getServiceManager ();

  IServiceHandler downloadHandler = new DownloadServiceHandler();

  manager.registerServiceHandler( "downloadServiceHandler" , downloadHandler);

 

2 在客户端节本的调用

在 bowser 控件中书写 js 请求脚本,脚本请求的 url 如下

    private String createDownloadUrl(String fileName) {

        StringBuffer url = new StringBuffer();

        url.append (RWT.getRequest ().getContextPath());

        url.append (RWT.getRequest ().getServletPath());

        url.append ( "?" );

        url.append (IServiceHandler. REQUEST_PARAM );

        url.append ( "=downloadServiceHandler" );

        url.append ( "&fileName='+encodeURI('" );

        url.append (fileName);

        url.append ( "')" );

        return url.toString();

    }

3 服务器端 handler 的写法

public class DownloadServiceHandler implements IServiceHandler {

   public void service() throws IOException, ServletException {

      String fileName = URLDecoder.decode (

            RWT.getRequest ().getParameter( "fileName" ), "UTF-8" );

      String filePathAndName = null ;

      try {

         filePathAndName = FileUtil

         .getTempFilePathAndName (RWT.getRequest ().getSession()

                      .getAttribute( "userName" ).toString(), fileName);

      } catch (Exception e) {

         throw new IOException(e);

      }

      File file = new File(filePathAndName);

      if (!file.exists()) {

         return ;

      }

      HttpServletResponse response = RWT.getResponse ();

      response.setHeader( "pragma" , "no-cache" );

      response.setHeader( "cache-control" , "no-cache" );

      response.setDateHeader( "Expires" , 0);

      response.setCharacterEncoding( "UTF-8" );

      response.setContentType( "text/html;charset=UTF-8" );

      response.setHeader( "Content-Disposition" , "attachment;filename="

            + new String(fileName.getBytes( "gb2312" ), "ISO8859-1" ));

      try {

         BufferedInputStream in = new BufferedInputStream(

                new FileInputStream(filePathAndName));

         ByteArrayOutputStream out = new ByteArrayOutputStream(1024);

         byte [] temp = new byte [1024];

         int size = 0;

         while ((size = in.read(temp)) != -1) {

            out.write(temp, 0, size);

         }

         in.close();

         byte [] content = out.toByteArray();

         response.setContentLength(content. length );

         response.getOutputStream().write(content);

      } catch (IOException ioe) {

         throw new RuntimeException(ioe);

      } finally {

         try {

            FileUtil.deleteTempFile (RWT.getRequest ().getSession()

                   .getAttribute( "userName" ).toString(), fileName);

         } catch (Exception e) {

            throw new IOException(e);

         }

      }

   }

}

 平常进行 rap 程序开发一般都是在 win 下面完成 , 然后在 tomcat 下面测试 , 但是程序最终发布一般都是在linux  aix 上面 , 这个时候就有能会出现一下问题,下面 2 个问题是我们把在开发中真是出现的问题,与大家一起分享下 ;

1、   图片路径

这个是最常用的方法,就是在 rap 中加载图片进行显示,刚开始我们使用的是如下代码

 

Java代码   收藏代码
  1. public static String getRoot() {  
  2.         String path = null ;  
  3.         try {  
  4.      path = FileLocator.toFileURL (Platform.getBundle (Activator. PLUGIN_ID ).getEntry( "" )).getPath();  
  5.      path = path.substring(path.indexOf( "/" ) + 1, path.length());  
  6.         }  
  7.         catch (Exception e) {  
  8.            log .error( "getRoot method :" , e);  
  9.         }  
  10.         return path;  
  11.     }  

 

来获得系统的跟路径 . 但是当程序在移植到 linux 和 aix 上面的时候发现图片路径全部失效 . 可以使用如下方式进行寻址来获得图片。

Java代码   收藏代码
  1. /** 
  2.      * 获取图片 
  3.      * @param fileName 
  4.      *            图片的名称 
  5.      * @return 先从缓存对象中查找,若有直接返回,若没有,则将图片加载到缓存中,在从缓存中将图片传给调用着 
  6.      */  
  7.   
  8.     public static Image getImage(String fileName) {  
  9.         Bundle bundle = Platform.getBundle ( "TelecomUI" );  
  10.         URL url = bundle.getEntry( "icons" );  
  11.         try {  
  12.             url = Platform.asLocalURL (url) ;  
  13.         }  
  14.         catch (Exception e) {  
  15.         }  
  16.         Image image = registry .get(fileName);  
  17.         if ( null != image) {  
  18.             return image;  
  19.         }  
  20.         else {  
  21.             URL fullPathString = bundle.getEntry( "icons/" + fileName);  
  22.             ImageDescriptor des = ImageDescriptor.createFromURL (fullPathString);  
  23.             registry .put(fileName, des);  
  24.             return ImageDescriptor.createFromURL (fullPathString).createImage();  
  25.         }  
  26.     }   

 

 

 

2、   获得屏幕的分辨率

因为需要把一些弹出的组件居中显示 , 这个时候就需要获得系统的分辨率

刚开始我们使用的方法如下;

Java代码   收藏代码
  1. screenH = Toolkit.getDefaultToolkit().getScreenSize ().height;  
  2.         screenW = Toolkit.getDefaultToolkit().getScreenSize ().width;   

 

 

上面这段代码在 window 下面是没有问题的 , 可是到了 linux 和 aix 下面就报错了 , 找不到

sun.awt.X11.XToolkit 类

 

可以采用如下方式来获得屏幕的分辨率     

Java代码   收藏代码
  1. DisPlay.getDefault().getClientArea();  

 

 

3、   其他如果有发现不兼容会陆续补充


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值