RCP机制
东方俊力
2023-12-01
参考网站:
http://wiki.eclipse.org/JFaceSnippets
学习资料:
书:通过例子学习RCP
ECLIPSE插件开发
网站:IBM关于SWT的 http://www.ibm.com/developerworks/cn/opensource
http://www.java2s.com/Code/Java/SWT-JFace-Eclipse
存在的问题:对逻辑不熟,因此做出来的东西有些逻辑可能有问题,因此需要懂逻辑的人来修改后台功能性BUG和做新功能;
12月份完成功能:
1.点击弹出SVG图功能
2。订购功能
3.订购对话框
4.进度条
5.更新插件
6.BUG修改
RCP的特别之处:
1.采用OSGI类加载体系,故会有一系列涉及到类加载器的异常;
2.RCP采用的多线程机制,有时会发生和多线程相关的异常,这种异常很难查明原因;
3.RCP的异常处理,很多异常在RCP中不会抛出,只会使程序停止运行,使得发现不了异常(如空指针异常)
4.RCP采用插件运行机制,故在其中采用的CLASSPATH等相对路径与其它JAVA程序中的路径不同,会产生问题;
对原框架的修改:
1.所有与ActionSupport藕合的Action,要么在BaseAction中进行覆盖该方法,不能用此方法的则在Action中进行修改;
2.原框架也新建了一个SPRING容器,用来对继承的一些属性进行对应更新,对其进行了修改;
3.为了加快速度,禁用了二级缓存
未来要做的改进:
现在通过结果拿到的是对象,未来做成像JSP那样,所有的对象都转化为MAP(在使用BEANUTILS包实现时,遇到比较奇怪的BUG,待未来研究完TOMCAT机制后再做会好些);
1.RCP启动
(1)RCP启动时,会先寻找扩展点"org.eclipse.core.runtim.application"定义的类,通过调用该类的start方法来创建并运行工作台
同理,也通过调用该类的stop方法来关闭窗口;
(2)接下来,工作台通过WorkbanchAdvisor进行配置,通常实现的为它的子类;
(3)工作台会启动动一个WorkbenchWindow,此窗口通过WorkbenchWindowAdvisor配置,同样实现的为它的子类;
(4)WorkbenchWindow将创建工具条,此工具条可以通过ActionBarAdvisor在启动时配置。
2.添加动作
添加动作选项&&触发动作定义&&及动作执行操作的定义
1.添加动作选项
其实就是在菜单栏中添加对应的选项,通过org.eclipse.ui.menus扩展点进行,
其中New->menuContribution中的locationURI(定位URI)定义菜单栏在工作台中的位置(menu:org.eclipse.ui.main.menu);
New->menu添加一个菜单,其中Label定义菜单名字 New->Command添加一个带响应动作的菜单项,其中commandID定义该动作对应的ID(注意,该ID和随后定义的command扩展点的ID必须一致,这样才会在点击该菜单时执行相应动作),Lable定义菜单项名称,tooltip定义的是提示的内容;
2.触发动作定义(什么动作时调用操作)
汗,好像没有,直接就是点击时响应,这个需要在随后研究一下,因为改造时需要有根据焦点在改变一些动作;
3.动作执行操作的定义(什么操作)
通过org.eclipse.ui.commands扩展点进行,
id定义该动作的ID,注意该id必须与其所关联的菜单项的commandID一致;
name定义该动作的名字,其实可以随便写的;
defaultHandler定义该动作的执行类,通过覆写其execute方法来定义相关动作;
3.添加编辑视图
主要包括两块,左边的VIEW视图和右边的编辑视图;
编辑器通过org.eclipse.ui.editors来扩展,同样ID,CLASS,其中ID主要还是为了调用时的ID方便,不再详述;
定义类除了editor外,还是定义对应的INPUT类,其实就是输入框生成时的的默认值 ;
还需扩展commands来定义一个CALL类,即点击动作时来动态生成新的窗口;
4.添加视图组件
5.editor的INPUT
使用INPUT的equal方法来判断是否为同一页面,如果为同一页面,则显示该页面,如果不是,则打开一个新的页面;
为了进行数据刷新,则必须采用每次都关闭打开的方法;
6.SVG生成
1.添加侦听动作,生成相应 ACTION
2.两部分:一部分SVG,一部分LIST;
SVG:手工将POINTS结果拼成String,显式初始化Points;
LIST:根据JSP生成对应LIST,添加鼠标动作侦听; 添加订购及显示动作侦听和相应的对应框;
二.基于RCP的C/S体系设计
仍采用MVC模式来设计,
其中MODEL层仍采用原项目中的SPRING,所有ACTION的配置改为scope="prototype",model层为了更新MODEL的公共字段,使用了手工再生成一个SPRING工厂的方法,替换该 方法;
1.VIEW层改用RCP,
VIEW主要包括界面生成,监听函数:
其中监听函数的实现需要调用ACTION的用命令模式来实现,即调用一个通用的COMMAND对象,对应的参数MAP(对应的ACTIONID和方法名分别用特定的KEY值:action.class.id,action.method.id);当然,更好的办法是直接封装成一个对象,以防止该MAP中的ACTIONID和方法名为空传到CONTROL层;
返回的结果也采用MAP形式;因为是本地单机版,故所有的MAP可以存各种对象,而不只是String;
为支持国际化,故VIEW层的所有字符都由UTIL包的LanguageProp类来提供;
其中VIEW层转换为RCP的最大的问题可能在于动态生成JS的技术替换,这个该框架用得不多;
动态生成JS或者JS命令,即不同的返回参数会生成不同的JS命令,如果用JAVA来模拟,因为JAVA不是动态语言,故不可能动态生成JAVA命令,因此只能手工实现所有的
命令,这个会很麻烦,特别是如果动态生成的JS命令有非常多的时候;当然,可以用JAVA的基于ASM的字节码技术来动态生成对应的JAVA类来实现,但这样的话,一来
对技术要求很高(ASM并不是一个非常友好的框架,要求对JAVA的字节码格式等很熟才行),二来非常麻烦;
2.CONTROL层主要模拟STRUTS层功能:
通过ACTION对象ID来由SPRING的对象工厂得到对应的ACTION对象,通过反射方法来完成ACTION对象的参数自动填充,通过MAP中的一个特定参数(如command.method)来调用该ACTION的特定方法来完成相应功能;
B/S结构的返回对象有两种,一种是返回的字符串,另一种是设置Action里面的属性,然后在JSP中将其读取出来;
其中字符串用于转向机制,应该用不到,保险起见,作为一个特殊对象存放;
该层因为继承了ActionSupport而与WEB发生藕合,故需要覆盖发生藕合的方法
Action里的属性全部作为MAP传回,因为通常VIEW层用到的ACTION层的参数只是一小部分,为效率考虑,不再转为MAP,而是封装后直接传回Action对象,取值时再进行相应反射得到对象,得到的对象为OBJECT对象,需要人工强制转换一下;
Action使用COOKIE来存储SESSIONID和用户名,通过查看COOKIE中的用户名来确认当前用户,需改写,改为使用一个静态类来存储该信息;
备注:事实上甚至可以在CONTROL层完全模拟STRUTS功能,使用类来读取对应的STRUTS配置文件,使得VIEW层不需知道后台对应的类ID和方法名,直接通过ACTIONID即可调用相关方法,并不算复杂;因为本项目涉及到的功能点较少,基于时间因素考虑,故未实现这一功能;
三.关于整合方案的思考
现在的整合方案是去掉STRUTS2层,将原来的MVC模式中的VIEW和CONTROL层的功能全部模拟;原以为STRUTS2只是一个转向功能,只要人工控制转向,再加上参数填充和国际化,即只要做一个工具类来实现一下即可完成;
但实际实现过程中却远比此要复杂,B/S项目中的action实现类都继承了STRUTS2中的ActionSupport类,也调用了该类中的方法,而ActionSupport类是与servlet藕合的
如
1.调用ActionSupport类实现国际化的方法,导致必须要替换该方法,否则所有action实现类都会有问题;
2.调用了ActionSupport类提供的获得HTTP请求内容以及向HTTP响应中直接写入内容的方法,这部分必须删掉并人工替换,因为这部分的内容很杂,有的是写入COOKIE,有的是直接写入了HTML,有的可能是写入JSON串,这些东西都无法在单机版C/S系统中直接使用的,因为对于涉及到的类只能一一具体实现来替换,成为了一个很大的工作量,如果将来单机版涉及到的功能多的话,这部分工作量会更大;
3.如果该STRUTS的转向机制中有不是根据结果直接返回JSP,而是返回重定向IP地址或跳转到别的ACTION的,则对于所有涉及到有这种配置的action实现类也必须一一替换,是一个很大的麻烦;
4.web.xml中的filter的问题,在B/S项目中,每个请求都会经过filter,再调用ACTION,这部分内容在C/S中要么忽略要么提供对应实现,但其中很多的filter都是直接调用开源包,重新将其改写为C/S难度太多,耗时过多;如spring用于实现request范围的action实例生成机制的filter(该问题直接导致所有的spring配置文件中的scope="request"必须手工替换为scope="prototype"),hibernate用于实现数据库session在session级别而非请求级别的复用的filter(因为本项目中虽然配置有该filter,但该配置选项其实相当于禁用该filter的,所以不实现也没关系,否则如果使用,且有依赖于该机制的代码,就会造成很难查到的BUG);
5.参数填充机制的实现,要实现参数的自动类型转换以及参数的自动填充
6.ACTION方法调用:STRUTS2通过自动根据参数调用对应类的对应方法,因此也必须要手动替换;
7.返回参数封装:STRUTS2将返回参数直接封装入HTTP的RESPONSE响应中,因此必须要手工替换;
8.拦截器的功能:该项目中需要替换的只有自动组装session的功能,较好做,但如果还有很多其它拦截器的话,则会比较麻烦;
9.验证框架的功能:该项目中没有用到,否则所有的验证框架都要手工用JAVA来实现;
以上几点中:问题1,5,6,7,8,9是技术问题,即需要手工实现这些功能,来替换原有STRUTS2的功能,但通常来说只需要添加类或更改所有ACTION的基类;
问题2,3则是工作量问题,难度不大,但因为需要手工修改涉及到的每个具体的action类,功能点较多时会造成较长的耗时;
另一个则是更改每个功能点都要人工分析一次该功能点的JSP,JS和STRUTS2的配置文件中的内容,来确定每个功能点实现的功能并在VIEW层和CONTROL层替换,在对项目不了解的情况 下,跟踪每个功能点的具体实现细节会花很长的时间;
问题4则是隐患,不同的filter实现在功能都是完全不同的,因此针对不同的filter配置,都要一一确定是否可又去掉或改造;
如此复杂的过程,自然要想一下,是否是方案的选择有问题,或许真的有更好的方案呢?
备选方案1:
不再重写CONTROL层,而是对其进行有限度的改造,即1,5,6,7,8,9仍然使用STRUTS2本身的机制来实现,但因为ActionSupport类实际上与Servlet藕合的,因此必须要研究ActionSupport类涉及到到所有功能实现在源码,确定哪些功能点的实现与Servlet无关,对ActionSupport类实现有选择的复用;
更进一步,可以研究一下ActionSupport类与Servlet藕合的功能点,对这些功能点的实现类进行人工替换以符合C/S的需要,这一步较难,但并非不可实现;
经过这两步,1,5,6,7,8,9技术点可以直接复用,当然,该过程要求对STRUTS2的大部分实现细节都了解到代码级别的层次,技术难度更大一些,但好处在于与原有代码的兼容性会更高;
备选方案2:
不再改造STRUTS2,而是做一工具类,手工实现STRUTS2中涉及到的J2EE规范中的一些接口类,来人工模拟HTTP请求,这样可以实现对STRUTS2最大程度的复用,印象中STRUTS2不只支持JSP技术,因此有可能只需要改写STRUTS2配置文件中的转向配置,则可以完成改造;这样上述的7点问题基本上都不存在了,对原代码的改动 量最少;
但这种方案需要对J2EE规范的实现和STRUTS2都有较深的理解,且因为涉及到的东西过多,个人感觉有失败的风险,即可能技术上根本不可行;但如果可以实现的话,则将来的所有B/S改为C/S的都可以利用这一框架,且代码改动量最少;
总体来讲,当前的方案应该是技术难度较小且把握度较高的一种方案,在涉及功能点较少的情况下,目前的方案应该是耗时最少的一种,但如果放在做一个通用技术框架的角度来看(即将来所有的改造都可以使用该框架来进行),该方案就不是耗时最少的方案了,也不是改造难度最小的一种方法,这种情况下,个人可能优选选择备选方案1,如果这种改造的应用非常的多,则可能会优先尝试备选方案2是否可行了;
国际化的一种高级方法:
动态生成一个JAVA类或接口,该类有N个static final字符串常量,对应于国际化文件中的对应变量,及其值;
相对于用静态为类加载来说,这种类可以直接使用类名.常量名来引用该字符串,但缺点在于如果文件很大的话会占用很大的方法区空间;
(不可行,因为继承该类或接口时必须要求该类文件是存在的,只要存在其常量就是固定的,不可能使用其中还没有的常量)
eclipse RCP 项目中文件编码为UTF-8时的导出问题(2011-05-27 13:32:43)转载▼标签: 杂谈
在eclipse RCP项目中使用UTF-8编码,源文件中包含中文,导出时报错。
报错为:
......
tableColumn.setText("鐧诲綍椤靛湴鍧?);字符串文字未用双引号正确地引起来
......
明显为编译时编码设置问题
先后用过的解决方案
1、用PDE工具创建Ant构建文件,然后修改build.xml,为javac标签加上encoding="UTF-8"属性,然后再导出。
很多教程中都是这么解决的,但是每次导出前都要做这些动作,很傻。
2、利用eclipse的构建,把source设置为bin目录,这样导出时直接导出bin,绕过编译过程。
问题很多:
不能同步build.properties的配置到eclipse构建路径,否则eclipse构建会有问题;
用eclipse直接运行时,需要勾选“定制构建”选项,导出时又要取消勾选。
3、在build.properties中加入javacDefaultEncoding.. = UTF-8 。
完美了