Eclipse e4开发-01-Eclipse RCP介绍
时间:2023-05-24 14:48:01 | 来源:网站运营
时间:2023-05-24 14:48:01 来源:网站运营
Eclipse e4开发-01-Eclipse RCP介绍:
原文链接
Eclipse RCP
知识点整理
参考书籍
必看
为了找到好的基于Eclipse 4平台之上的书籍少之又少,国内完全没有。国外的有不多。下面一一列举:
1. 最好的学习去处是一个培训网站,叫做Vogella,唯有这个网站还有些不错的文章和教程。要把这上面所有的教程都学习一遍,基本可以入门了。我这里有离线的pdf,但实际上还是这个网站的内容。因为这个网站的内容是持续更新的。
2.
Packt.Eclipse.Plug-in.Development.Beginners.Guide.2nd.Edition.pdf, 这本书需要一定的英文阅读能力,对于e4的内容不是最多的,但是本书的好处是有很多例子,书的结构非常好,理论少实践多,与上面的网站比差一些。书中也是有错漏的,我在学习过程中遇到过,我尽量记录矫正过来。
3.
Mastering.Eclipse.Plug-in.Development.pdf,这本书是Packt.Eclipse.Plug-in.Development.Beginners.Guide.2nd.Edition的高级篇,为同一作者所著。
4.
Eclipse_4_Tutorial.pdf, 这也是官方网站推荐的一篇文章,篇幅不长,但是可以看。
选看
参考链接
- Eclipse RCP E4 FAQ
- Vogella
- Equinox introduction
- OSGI and Equinox
基于Eclipse应用开发介绍
基于Eclipse的应用,叫做Eclipse RCP(Eclipse Rich Client Platform),用Eclipse框架来构建独立的丰富特性的桌面应用。
Eclipse IDE(Integrated Development Environment)可以看作是一种专注于软件开发的特殊的Eclipse应用,比如说JDT提供了java开发的集成环境。
一个Eclipse应用由独立的软件
组件构成,这里的组件就成为插件(Plug-in),在OSGI概念体系也叫做bundle。因为Eclipse框架是一个可扩展的框架,因此插件可以扩展另外的插件。比如,我们可以创建新的插件来创建新的菜单或者工具栏,来扩展Eclipse自带的菜单或者工具栏。
Eclipse IDE作为一个典型的Eclipse应用,使用了一些基本的组件,这些组件的组件用一张图可以描绘成下面这样:
1.Eclipse_base_components概念补充
Eclipse历史
Eclipse 3, 与OSGI的结合。 Eclipse 4,把UI变成EMF模型,这些模型通过POJO表示,然后这些POJO可以依赖注入。另外,e4平台的UI可以被诸如CSS来渲染界面。
插件(Plugin)
为了处理模块间的依赖关系,Eclipse提出扩展(Extension)和扩展点(Extension point)的概念。每一个希望被别的程序模块扩展的模块,都必须声明一系列扩展点,可以将扩展点想象成插座。而希望在这个模块上扩展功能的程序模块,就需要按照扩展点的声明来编写扩展,这个就是扩展,就像是插头。通过将插头插入插座,扩展获得了服务。即扩展点提供服务而扩展使用服务。这叫做声明与实现分离。扩展点和扩展也可以理解成父类和子类的关系。
通过这种机制,Eclipse平台和其他功能组件插接起来,就成了一个可用的系统。比如平台加JDT就成了Java IDE,平台加PDT就成了PHP IDE。所以,凡是遵循这一机制开发出来的模块,就叫做插件。这是Eclipse平台最重要的技术,一切都是插件。看看现如今的VSCode也是通过插件迅速赢得巨大的市场。
<!--Extension Point Declaration --><extension-point id="view" name="org.eclipse.ui.views" schema="schemas/views.exsd" />
以上是一个扩展点的声明,
name="org.eclipse.ui.views"
就是暴露出一个扩展点。
<!-- Extension Declaration --><extension point="org.eclipse.ui.views"> <view alloMultiple="false" class="com.mycompany.ui.MyView" id="com.mycompany.ui.MyView" name="MyView" />
以上是一个扩展的声明,扩展点和扩展是通过
"org.eclipse.ui.views"
这个名称关联起来的,扩展
point
扩展点,就像插头插进插座。
这也就体现了声明与实现分离,因为后面具体的实现都放在了类
class="com.mycompany.ui.MyView"
里面去实现,尽管在此刻
MyView
还没有诞生。
扩展和扩展点是Eclipse插件开发的最早实现,也是Eclipse 2就有的技术,通常被称为Eclipse runtime。但是从Eclipse 3开始,除了保留Eclipse Runtime的同时,对OSGI做了实现,新的框架被称为Equinox。
OSGI
OSGI(Open Services Gateway Initiative),开放式服务网关协议,是一套基于Java的开放式接口协议。它的思想与Eclipse插件的思想有些类似,都是希望将程序分解为小的可重用的组件,并通过组合它们来构成共嗯那个更强大的可执行程序。然而OSGI对于Eclipse开发者最大的吸引力,还在于它的框架体系实现了在运行时对模块动态添加和删除功能的支持。
RCP
RCP(Rich Clent Platform)富客户端平台,是帮助开发者创建和部署富客户端的平台。所谓富客户端指的是为用户提供丰富功能体验的客户端程序。通用,一个富客户端具备以下特征: 1. 应该是桌面程序而不能是web应用程序,即它可以暂时脱离网络运行,还可以访问客户端本地的资源如文件打印机等。 2. 界面美观,功能丰富,具备跨平台能力并且与操作系统的图形平台紧密结合,对用户操作响应要好。 3. 承担一定程度的数据缓存以及业务逻辑计算功能,减少和服务器端的交互,减轻服务器的负载。
在Eclipse平台的初始设计并不包含RCP的构想,从Eclipse 2开始,有的开发人员开始使用Eclipse平台开发别的类型的应用程序。到了Eclipse 3,Eclipse平台中和IDE关系紧密的插件被剥离出去,
剩下的插件集合就被作为RCP推出。这里面就包含了新的基于OSGI的运行时框架Equinox,基于SWT/JFace的图形模块、Eclipse平台的UI和Runtime模块。
Graphic Design is the what most people think of when they think of design because it's the easiest to observe. Graphic designers pick colors, choose images, design logos, and do other very visual tasks. This type of design is similar to what most people would consider "art".If graphic design is art, then User Interface Design is science. UI designers figure out how software and users interact with each other. When you submit a form, what happens? How are users notified of errors? Does the form go to a new page, or submit while staying on the current page? Great graphic design means the software looks pretty. Great UI design means the software is easy to use. Great graphic design is Apple. Great UI design is Google (many of their products anyway - just don't mention Android or Google Docs).
RCP是构建一个基于Eclipse平台技术的应用程序所需要的最小集合,但这并不意味只能使用这个最小集合中的插件。开发者可以任意选取其他插件并将其添加到这一集合之中。
SWT
SWT(Standard Widget Toolkit)标准图形工具箱,是Eclipse开发人员自行创作出来的图形技术。与jdk中的AWT和SWing不同。它无论在界面美观度还是在性能上都超越AWT和Swing。跨平台支持是Java GUI技术设计的最大难点,AWT设计理念是不同操作系统中取其交集,即支持每个操作系统都有的控件,导致只能支持最常用的控件和显示风格,AWT早已经没有多少人用了。后来Swing走了另外一条路径,它是除了标准的控件,支持手绘图形界面,不管各种操作系统是否支持,这样一来,在个平台都保持了一致,但是性能方面就不行了,目前只有Oracle的JDeveloper使用的这个技术,也是使用的非常少。
SWT实际上是综合了AWT和Swing的优点,尽量使用目标平台的控件,以达到较快的处理速度。实在是因为目标平台没有的控件,才进行Swing手绘控件。
JFace
JFace是一套基于SWT的工具箱,它将一些常用的界面操作包装了起来,对界面设计进行了更高层次的抽象,使得开发人员可以专注业务逻辑。在Eclipse平台中,就广泛使用了JFace,如“对话框”,“首选项设置”和“创建向导”等等,提供了实现框架,大大方便了开发者。
此外,他还有两个最吸引人的功能,操作(Action)机制和查看器(Viewer)机制。 - 操作机制是将一系列与界面操作无关的操作如对底层数据的修改,封装成一个操作对象,以进行复用。 - 查看器机制是指对一些复杂工作如表格、树和列表做的包装,使用起来更加便捷,查看器使用了MVC模式和数据绑定。
PDE
PDE(Plugin Development Environment)插件开发环境是Eclipse的一个子项目,为开发人员提供一个开发插件的环境,提供了一整套工具来对插件进行: - 开发 - 测试 - 调试 - 构建 - 部署
The Plug-in Development Environment (PDE) provides tools to create, develop, test, debug, build and deploy Eclipse plug-ins, fragments, features, update sites and RCP products. PDE also provides comprehensive OSGi tooling, which makes it an ideal environment for component programming, not just Eclipse plug-in development. -- http://eclipse.org
PDE基本包括几个模块: - PDE UI :主要是用来窗口界面各种wizard来完成插件的配置,将POJO模型转化为插件,和JDT集成等大部分插件开发所需的配置和代码。 - PDE BUILD:插件构建并非使用maven构建,而是更原始的Ant,只是这些构建脚本是自动生成的。 - PDE API Tools:
Workbench
Eclipse窗口又称为workbench(工作台),它包含几个部分: - 菜单栏 - 工具栏 - 编辑器 - 视图 - ...
Perspective
翻译为透视图,指的是工作台中一组视图和编辑器的初始布局。将一组业务功能相关的视图放置在同一个透视图下,方便开发人员专注工作,比如Java Perspective就是一个整体的界面适合Java开发的透视图。
View
视图容器,特点就是只能看不能编辑。有自己的菜单和工具栏,通过菜单Windown->Open View来打开的,可以单独出现,也可以和其他视图一起出现,通过拖拽方式改变位置。
Editor
编辑器一般是指与特定文件类型关联的编辑区域,如Java语言编辑器。
插件清单编辑器
这个文件位于RCP项目的根目录下,存放着几个重要的配置文件: - plugin.xml - MANIFEST.MF - build.properties - fragment.e4xmi/application.e4xmi
PDE提供了管理这些文件的界面:
- General Information
- ID 插件标识符 必填
- Version 版本号 必填
- Name 名称 必填
- Provider 供应商 选填
- Platform Filter 插件平台过滤器,用于表示插件运行的条件
- Activator 激活器,用于控制插件生命周期的Java类,仅当启动或关闭插件时执行的操作
- Execution Environment 执行环境,指定JRE的版本
Eclipse的版本号
首先要搞清楚Eclipse指的是一个平台, 当我们说Eclipse的版本比如4.16其实指的是SDK的版本,也就是说Eclipse SDK的版本号是4.16,SDK(Software Development Kits),这是最核心的版本。
SDK的下载网址是Eclipse SDK download, 最新的SDK是2021-12-24发布的4.22.最早的SDK是2001-12-07发布的1.0,可见,Eclipse SDK存活了20年了。
就如同java的JDK版本一样,当我们说java 8的时候,其实就是再说jdk的版本是1.8,同样的,当我们说eclipse 4的时候,也是再说我们的sdk是4.
Eclipse SDK是核心平台,也就是说是一个最小合集,在这个最小合集之上,可以加装很多扩展的插件,也就成了各种IDE,比如SDK+JDT就成了Eclipse Java IDE,SDK + PDT就成了Eclipse PHP IDE等等,因此就不能再使用SDK的版本号,而是新建了一个Eclipse IDE版本号系列,是以【年-月】的格式来定义的,比如2021-12是Eclipse IDE最新的版本号,它代表了一批IDE,如下截图:
2020-06版本的IDE关于IDE
除了从Eclipse网站下载官方发布的Java IDE之外,还有其他的IDE可以下载,例如我常常会使用
http://Spring.io提供的STS(Spring Tools Suite),它也是建立在Eclipse平台之上的对IDE的扩展,因为Spring目前实际上已经成为Java企业开发的事实标准,为了方便开发人员,Spring会发布STS,这个STS就和Eclipse网站发布的IDE除了SDK使用同一个,插件方面也很多不同。
例如笔者现在使用的STS的版本号是4.7.1,那么如何确认STS使用的SDK版本呢?可以通过Help->About STS来确认,截图如下:
使用STS,需要通过p2链接
http://download.eclipse.org/releases/latest,通过Help>Install New Software,输入上述网址,来安装
e4 tools插件。
What is p2? p2 is a provisioning platform for Eclipse-based applications. It replaces the older Update Manager as the mechanism for managing an Eclipse installation. Provisioning is the act of finding and installing new functionality, and updating or removing existing functionality; it is distinct from building.
e4核心概念和编程模式
理解e4概念非常重要的原因,是因为在Eclipse platform亦即Eclipse SDK版本4基础上的RCP应用开发与在Eclipse 3的RCP开发差别很大。e3引入了OSGI,e4引入了模型设计和依赖注入。鉴于eclipse rcp开发比较小众,基于e4的书籍和教程较少,看来看去还是vogella网站的最好了。包括OSGI,这个技术也就Eclipse在用,所以之前调查过spring osgi这个项目,最后也是没有再更新,说明spring也放弃了osgi。话说回来,e4平台与e3的差别较大,对于新开发的插件,直接从e4的RCP开发开始学,e3的东西可以放弃了。
更精确一点说,典型的e3或者叫Eclipse 3.x编程模式就是在plugin.xml中广泛使用Extension和Extension Point来进行声明和实现新的菜单按钮等等的话,那么e4的编程模式就是通过fragment和processor这样的核心概念来进行设计,很少和plugin.xml打交道了。下面详细介绍一下e4编程模式(programming model)。
首先通过完成练习3. Exercise: Create an RCP application with the wizard来对e4 RCP有一个直观感受,通过向导和模板我们建立了一个算是RCP的Hello World例子。
这个例子在STS上已经进行测试: - STS 4.7.1 - JDK 1.8 - Windows 10
运行成功后,我们来看一下e4的编程模式,打开工程:
Simple RCP Project Structure- JRE 1.8的依赖自不用说
- 插件依赖,这里可以看出e4应用依赖的基础插件包括:
- javax.* 依赖的是注解,因为e4开始鼓励使用注解来实现依赖注入(DI)
- org.eclipse.core.* e3就有,eclipse平台核心的类库
- org.eclipse.swt.* e3就有,SWT(Standard Widget Toolkit)是Eclipse特有的图形解决方案,在别的地方我有介绍//TODO
- org.eclipse.jface.* e3就有,jface是SWT的封装
- org.eclipse.osgi.* e3就有,osgi的包,OSGI主要是定义服务的模块化接口定义
- org.eclipse.equinox.*,e3就有,是对osgi接口的实现。
- org.eclipse.e4.ui.*, 这就是重点,是e4特有的东西,它对UI进行了重新定义,分为model,service,di和workbench几个包。重中之重。
- src里有两个包,handlers放的是实现command的代码,而parts放的是实现窗口控件的代码。
- css,这个也是e4才有的,借鉴了前端开发的CSS,因此可以使用css来负责前端控件的显示风格。
- icons,这里主要是资源文件,放一些图标文件
- META-INF,这里有一个重要的文件是MANIFEST.MF,这倒是个java标准,中文翻译为资源配置清单,是在部署时用此来说明该部署保重包含了什么文件。
- application.e4xmi,这个文件定义了应用模型,即应用的UI是什么样子的,怎么初始化,事件如何相应等等,这就是编程模式中提到的fragment存放的地方,是项目启动最重要的文件。
- build.properties,这个文件几乎不需要我们关心,是编译这个插件工程需要用的。
- com.example.e4.rcp.product,这个是产品文件,是e4的标准文件,有界面可以帮助我们如何配置这个产品。
- plugin.xml,这个文件在e3非常重要,在e4几乎不重要,可能在某些场合还是需要去修改一下的。
fragment.e4xmi和application.e4xmi都可以作为模型文件,本质上是一样的,fragment.e4xmi可以引用别的fragment,但需要在plugin.xml中指定。而application.e4xmi是默认的文件。
总结一下,在e4应用的编程模式中,我们前面提过两个概念:fragment和processor,在上面的工程结构中已经得到体现,也就是说,我们开发RCP的一般套路就是通过application.e4xmi/fragment.e4xmi来进行界面的设计,在src代码里实现窗口以及菜单命令的实现,然后产品配一配就可以完成开发了,算是入了门。
理解了这些顶层设计之后,我们开始下钻到各个部分了。
fragment中的model element和model object
在e4应用开发中,界面被描述在fragment文件里(application.e4xmi),他们是以模型出现的,在设计态,我们称之为model element,也就是模型元素,相当于java中的类,当他们处在运行态或者说运行时,这些模型元素就被实例化成对象,因此称之为model object。这些模型元素从上至下的结构包括:
- Application,接口名是MApplication,可以通过ctrl+alt+T查看。这是应用的root元素。
为了查看这些类的源代码,需要安装反编译插件,通过marketplace搜索【Enhanced Class Decompiler】,目前版本为3.2.2。下载安装之后,注意在preference里关联.class without sources到decompiler并设置为默认,重新打开class文件,就可以看到了,官方网站是ECD,如果是云上无法下载插件的话,可以通过安装离线包,或者把Eclipse从云下拷贝到云上。
- Window,每个Application由一个或多个窗口组成,接口类是MWindow或者MTrimmedWindow,MTrimmedWindow可以包括工具栏。
- Part,这是个新概念,在e4开发中,一个窗口被划为多个部分(Part),一个Part是一个组件的集合,可以拥有自己的下拉菜单、弹出菜单和工具栏,用来浏览或修改数据。Part分为View和Editor,View是用来展示和修改一组数据,例如树形或者表格。IDE中有很多view,比如Project Explorer视图,可以用来展示工程的文件结构,也可以在上面修改文件名,修改不需要显示去保存。而Editor是用来修改单个数据元素的,修改后需要显示保存,如果不保存就会在文件名左边出现一个星号(*)来标识这个Editor,成为Dirty Editor。单个Part可以直接挂在一个Widnow或者perspective。多个Part需要存放在容器里进行排列,有两种容器分别是Stack容器和Sash容器,区别在于排列的风格不同。接口是MPart。
- Perspective,这是一个容器,这个概念我们并不陌生,比如当我们需要debug一个java程序时,IDE会提醒我们切换到debug perspective,翻译成中文可以叫做透视图,它的作用是从功能的角度将一些协作紧密的模型对象摆放在一起。其接口为MPerspective,必须放在MPerspectiveStack的容器里并且只能有一个对象。
- 其他重要模型对象:
- MAddon,界面不可见的模型对象,一般用来监听特定的生命周期的事件并进行处理。
- MDirtyable,如前面提到过,此模型对象包含脏数据。
- MPartDescriptor,这个模型是一个模板,可以在此基础上创建新的part。
- Snippet,这是个代码片段,可以在运行时通过它生成一个模型对象并附在应用模型上。
从application.e4xmi编辑器上可以看出模型之间一些关系上面application.e4xmi中定义的算是应用的UI设计,这里有两点需要注意:
- 这里UI设计有一个缺憾,那就是到达窗体之后就结束了。具体的窗体UI,即按钮文本框等具体的元素则需要由指定的java类来完成,而那里是Eclipse3平台的内容了,即SWT和JFace用武之地的地方,在这里e3和e4是一样的,也完成了很好的衔接。
- 在application.e4xmi里要需要关联好part和类实现,以及command和实现类。
Contribute
这里需要有点悟性,为了区分e3和e4,在e4平台下很多概念都进行了重新划分,在e3开发的时候普遍使用plugin.xml中的extension来实现了窗口的扩展点(extension point)来得到插件。而在e4我们不再使用extension这个概念,而是换了个概念叫做contribution。通过对application model进行contribute得到了插件。
有两种方式对应用模型进行contribute(这里我不想翻译成贡献): - 静态方式,即创建自己的fragment.e4mi文件,这种就叫做model fragments - 动态方式,即通过java代码,这种就叫做model processors
创建一个标准的e4应用的标准套路
- 通过向导创建插件ui工程
- 创建一个feature工程,把上面创建的ui插件添加
- 创建一个product工程,再把feature添加到产品中
依赖注入(DI)
之前第一次听到依赖注入是在学习Spring的时候,这应该是spring的独创,后来影响到了整个java世界。e4开发一个很重要的改变就是使用依赖注入,和Spring实现不太一样,使用的注解是JSR的标准注解。如@Inject @Optional @Named。有几点需要注意:
- 遵守JSR330
- 最重要的几个注解:
- @Inject是JSR330的标准,相当于Spring的@Autowired
- @Named也是JSR330的标准,用来指定key,相当于Spring里的@Qualifier
- @Optional,Eclipse特有的,相当于Spring的@Autowird(Required=false)
- 在e4应用启动时,会扫描插件代码里的java类的注解,将这些对象放到上下文里
- 当对象在上下文中有变化时,会被重新注入
- 支持注入OSGI标准的服务
Eclipse Context 上下文
这是依赖注入的必然结果,上下文是一个容器,思路都一致,不再赘述。
这里重点是e4里有本地上下文(Local Context)的概念,即按照application model层级结构,在每一层都有自己的上下文,所以同样的key在不同中得到不同的对象。层级如下
graph TD; Application --> Window1; Application --> Window2; Window1 --> Perspective; Window2 --> Part1; Perspective --> Part2 Perspective --> Part3
按照这个层级关系,e4框架会自下而上的每个上下文容器里寻找对应的对象。上下文容器里摆放了三类对象:
- 模型对象,即实例化的UI模型
- 服务,即OSGI服务或者Eclipse平台服务
- 其他显式添加到上下文的,比如可以通过代码方式把之前Spring里面的对象添加进来以达到复用。
特殊用法
可以自动注入当前活动的part或者shell。 比如:
@Named(IServiceConstants.ACTIVE_PART)@Named(IServiceConstants.ACTIVE_SHELL)
使用注解定义行为
这篇文章有几句非常精辟的话,尤其是第11节(Using annotations to define behavior),比较抽象,需要反复领悟。
If you use a framework in your application, you need to have a convention for how your application interacts with the framework. For example, if a java object is reponsible for handling a toolbar button click, the framework needs to know which method of this object needs to be call.
For this purpose, every framework defines an API, this API defines how you can interact with the framework from your code. The API also defines the interaction of application objects created or controlled by the framework. Typically, a framework use inheritance or annotations for this purpose.
这段论述引出了框架和应用以及框架如何控制应用的问题,e3的时候,为了控制应用的控件和服务,使用继承的方式,现代观念一致反对继承,会提高代码的耦合性。
所以e4平台的API设计是基于注解的,用于标识某个方法在某个时间点被调用。这类注解又被称为
行为注解。
注解 | 描述 |
---|
@PostConstruct | 在对象被实例化后,被此注解的方法被框架调用 |
@PreDestroy | 在对象被销毁之前,被此注解的方法被框架调用 |
@Focus | 在当前part获得焦点时,被此注解的方法被框架调用 |
@Persist | 在保存动作触发时,被此注解的方法被框架调用 |
@PersistState | 和@PreDestory类似,当在@PreDestory之前 |
其中,@PostConstruct和@PreDestory是jdk中定义的标准注解,后面三个是e4平台定义的。
command 和 handler
在e4的UI中,除了窗体,还有菜单、弹出菜单、菜单栏按钮等控件,e4将控件、命令和实现分开,控件定义UI,command定义了该命令的属性以供复用,handler则定义了该命令被执行的内容,在application.e4xmi中有实践。一般来说设计时,将command和handler实现好,再挂载到具体的控件上。
关于handler的行为注解主要有两个: - @Execute,是用来标识该方法会在command从界面上被按下时被执行 - @CanExecute,被此注解的方法返回true或false,是用来辅助@Execute的,也就是说在执行@Execute注解的方法之前,会测试一下是否可以执行。
最后,值得提醒的是可以直接使用e4预先定义好的command,这样就不用自己实现其handler了。
以下是其列表:
本文完。