rap开发与rcp开发
使用Eclipse Rich Client Platform(RCP),您可以构建应用程序。 这些丰富的应用程序基于动态插件模型,并且使用常见的工具箱和扩展点来构建UI。 在开放工具开发中,Eclipse RCP被广泛使用。
Rich Ajax平台(RAP)项目使您可以使用Eclipse开发模型,插件和仅Java的API来构建支持Ajax的丰富Web应用程序。 RAP的目标是使RCP应用程序能够在Web浏览器中运行,而只需进行尽可能少的修改。
RAP和RCP具有相同的接口,但是它们的基本实现有很大不同。 RAP提供了一种称为RWT的SWT API的替代实现,它在Tomcat之类的servlet容器上运行。 客户端可以使用标准的Web浏览器(例如Internet Explorer或Chrome)访问它。
RAP和RCP应用程序用于不同的用户环境。 作为桌面应用程序,RCP一次只能与一个用户一起使用。 相反,RAP应用程序是基于Web的程序,可以由多个用户同时访问。 RAP基于Equinox,服务器端OSGi和运行时捆绑包。 每个Web应用程序一个OSGi实例在一个应用程序范围内运行。 与RCP相对,RAP必须处理用户会话和在用户会话之间共享的捆绑。
在本文中,将学习RAP的主要功能以及如何使用RAP将RCP应用程序迁移到Web。 您可以下载本文中使用的示例代码。
RAP流行于从单一代码库(也称为单一来源)开发富客户端应用程序和Web应用程序。 您可以将现有的RCP开发技能和代码库重新用于基于Web的RAP应用程序。 对于当前版本的RAP 1.3.x,可以在RAP环境中重用现有RCP代码的70%-90%,而无需进行更改。
RCP和RAP具有不同的API,功能,UI库,扩展点和用户环境。
PhaseListener
, ISessionStore
等。 要处理不同的API,请考虑以下建议:
“ 单一采购示例 ”部分中提供了示例源代码。
org.eclipse.ui
插件为RCP或org.eclipse.rap.ui
插件用于RAP)。 两者都需要作为主机的必需插件导入。 为了避免在使用不同目标运行时间时发生编译错误,请启用“属性”下的“ 可选”复选框, 如图1所示。 通过这种方式,RAP / RCP运行时将在开始执行时加载正确的库。
bindings
和helpSupport
)。 由于特定于Web的要求,RAP包括一些附加的E-P,例如entrypoint
和themes
。 引入了OSGi片段来处理不同的E-P,并对RCP和RAP使用相同的代码库。 片段是特殊的OSGi捆绑包; 它们扩展了另一个捆绑包,并且可以在运行时与扩展捆绑包合并。 首先,定义一个主机插件,其中包含RCP和RAP的通用代码。 然后,分别为RAP和RCP创建两个单独的片段,其中包括RAP和RCP的特定于平台的代码。 在运行时,将仅与主机插件一起安装一个相应的片段(RAP或RCP)。 因此,特定于平台的EP扩展名可以移至相应的片段,并且捆绑包结构保持完整。
SessionSingletonBase
该基类为每个会话提供了单例实现,并且避免了不同用户之间的应用程序状态共享。 会话单例是特定于RWT的单例,它提供对会话范围内唯一实例的访问。 在一个用户会话的上下文中, getInstance(Class)
将始终返回相同的对象。 但是,对于不同的用户会话,返回的实例将不同。
要实现会话单例类,应调用SessionSingletonBase#getInstance()
,该类将照顾单例实例的适当范围。 清单1显示了这种模式。 请参阅相关主题 RAP的常见问题解答。
package com.ibm.msdk.ui.configWas;
import org.eclipse.rwt.SessionSingletonBase;
public class SampleSessionSingleton{
private SampleSessionSingleton(){}
public static SampleSessionSingleton getInstance(){
return (SampleSessionSingleton)SessionSingletonBase
.getInstance(SampleSessionSingleton.class);
}
}
在本节中,将为HTML查看器提供一个示例RCP应用程序,以了解有关单一采购的更多信息。 您可以下载本文中使用的示例代码。 该示例具有一个用于显示HTML文件的视图,可以使用其工具栏上的“ 打开”按钮来打开该视图, 如图2所示:
该示例使用浏览器窗口小部件显示HTML文件。 要实现该功能,您需要创建一个名为com.ibm.msdk.example
的样本插件。
如前所述,样本插件中有RAP / RCP平台特定的代码。 您必须首先从示例项目中提取通用代码。 通过分析代码,从RCP HTML查看器中识别出不支持RAP的API: FileDialog
# open
(在com.ibm.msdk.example.action
包中),如清单2所示:
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchWindow;
import com.ibm.msdk.example.utils.HtmlFileReader;
public class ImportHtmlAction extends Action {
public static final String ACT_IMPORT_FILE = "ACT_IMPORT_FILE";
private IWorkbenchWindow workbenchWindow;
/**
* Constructs an instance of ImportHtmlAction
by given
* text and IWorkbenchWindow
.
* @param text
* @param workbenchWindow
*/
public ImportHtmlAction(String text,IWorkbenchWindow workbenchWindow){
super(text);
this.workbenchWindow = workbenchWindow;
}
/**
* Creates a file dialog for opening a new file,calls the method
* {@link HtmlFileReader#fetchHtmlContents(String)} to fetch the contents
* of the passed HTML file. Then fires the listener of HTMLView
* to refresh the contents of the view.
*/
@Override
public void run(){
Shell shell = workbenchWindow.getShell();
FileDialog fileDialog = new FileDialog(shell,SWT.OPEN);
String filePath = fileDialog.open();
String htmlContents = null;
if(filePath != null)
htmlContents = HtmlFileReader.fetchHtmlContents(filePath);
firePropertyChange(ACT_IMPORT_FILE, null, htmlContents);
}
}
在RAP中, 上传文件而不是打开文件是有意义的。 “ RAP上传项目”提供了这样的上传功能; 可以从RAP CVS存储库(sandbox / org.eclipse.rwt.widgets.upload)下载。
因为com.ibm.msdk.example
插件既针对RAP平台,也针对RCP平台,所以必须将这两个平台的必需软件包作为必需插件导入。 例如,需要UI捆绑包org.eclipse.ui
(RCP)和org.eclipse.rap.ui
(RAP)。 如图3所示,在插件的Properties中将不同的UI捆绑包的依赖关系设为Optional ,以避免在不同的目标平台上编译错误:
平台运行时环境(RCP或RAP)将加载正确的捆绑软件。 由于它具有两个目标平台,因此您需要创建两个新的片段来保存特定于平台的代码。 如图4所示,片段的主机插件属性设置为com.ibm.msdk.example
插件:
RAP没有FileDialog小部件。 您必须使用一个新的小部件,该小部件可以将文件从客户端上传到服务器。 幸运的是,RAP CVS提供了一个自定义的上载小部件,可以从存储库位置URL:pserver:[email protected]:/ cvsroot / rt下载,从org.eclipse.rap / sandbox / org.eclipse中找到该小部件。 rwt.widgets.upload。 为了使上载的小部件能够正常工作,需要org.apache.commons.fileupload
和org.apache.commons.io
插件。 两者都可以从资源库位置URL:pserver:[email protected]:/ cvsroot / tools下载。 从org.eclipse.orbit /中找到插件。 请参阅相关主题更多有关如何使用CVS下载。
doViewHtml()
的抽象方法,如清单3所示: /**
*
*/
package com.ibm.msdk.example.actions;
import org.eclipse.jface.action.Action;
import org.eclipse.ui.IWorkbenchWindow;
/**
* @author Minghai.Wang
* @version 1.0 2010-10-26
* @since JDK1.6
* @email [email protected]
*/
public abstract class AbstractViewHtmlAction extends Action {
protected IWorkbenchWindow workbenchWindow;
public static final String ACT_IMPORT_FILE = "ACT_IMPORT_FILE";
public static final String INSTANCE_CLASS = "com.ibm.msdk.example
.actions.ViewHtmlAction";
/**
* Constructs an instance of AImportHtmlAction
by given
* IWorkbenchWindow
.
*
* @param workbenchWindow
*/
public AbstractViewHtmlAction(IWorkbenchWindow workbenchWindow) {
this.workbenchWindow = workbenchWindow;
}
public void run() {
doViewHtml();
}
/**
* Abstracts the method for viewing the given HTML file.
*
* It is different between RCP platform and RAP platform.
*
* - In the RCP fragment,open a file dialog and select a HTML file that
* will be parsed, and then show it.
* - In the RAP fragment,upload a parsing HTML file, then show it.
*
*/
public abstract void doViewHtml();
/**
* @return the workbenchWindow
*/
public IWorkbenchWindow getWorkbenchWindow() {
return workbenchWindow;
}
/**
* @param workbenchWindow
* the workbenchWindow to set
*/
public void setWorkbenchWindow(IWorkbenchWindow workbenchWindow) {
this.workbenchWindow = workbenchWindow;
}
}
doViewHtml()
操作,需要修改主机插件的调用者部分。 清单4显示了原始类中的方法。 public class HtmlContentsView extends ViewPart implements
IPropertyChangeListener {
...
...
/**
* Fills the tool bar of the HTML view with a importing HTML action. A
* listener is added to the created action of importing HTML view.
*/
protected void fillToolBarAction() {
ImportHtmlAction importHtmlAct = new ImportHtmlAction("Open...",
getViewSite().getWorkbenchWindow());
IToolBarManager toolBarManager = getViewSite().getActionBars()
.getToolBarManager();
toolBarManager.add(importHtmlAct);
importHtmlAct.addPropertyChangeListener(this);
}
...
}
您可以在com.ibm.msdk.example
插件的HtmlContentsView.java中使用Java反射来获得新的片段操作,如清单5所示。 在RCP片段和RAP片段中创建的子类的全名应该相同。 以这种方式,在不同的运行时平台(RCP或RAP)上,将加载适当的片段,并调用适当的doViewHtml()
操作。
public class HtmlContentsView extends ViewPart implements
IPropertyChangeListener {
...
/**
* Fills an instance of AbstractViewHtmlAction
* that is created by Java reflection.
*/
protected void fillToolBarAction() {
try {
Class> clazz = Class
.forName(AbstractViewHtmlAction.INSTANCE_CLASS);
Constructor> cons = clazz
.getConstructor(IWorkbenchWindow.class);
AbstractViewHtmlAction viewHtmlAction = (AbstractViewHtmlAction)
cons.newInstance(getViewSite().getWorkbenchWindow());
IToolBarManager toolBarManager = getViewSite().getActionBars()
.getToolBarManager();
toolBarManager.add(viewHtmlAction);
viewHtmlAction.addPropertyChangeListener(this);
// Add an action for viewing singleton info.
ViewSingletoInfoAction viewSingleton = new ViewSingletoInfoAction(
getViewSite().getWorkbenchWindow());
toolBarManager.add(viewSingleton);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
...
}
在为特定于平台的功能定义抽象类之后,您需要分别在RCP片段和RAP片段中分别实现抽象方法。 在RCP片段中,创建一个扩展抽象类AbstractViewHtmlAction
的新类,如清单6所示。 它实现了使用FileDialog打开HTML文件的abstract方法。
public class ViewHtmlAction extends AbstractViewHtmlAction {
...
/**
* Creates a file dialog for opening a new file,calls the method
* {@link HtmlFileReader#fetchHtmlContents(String)} to fetch the
* contents of the passed HTML file.Then fires the listener of
* HTMLView
to refresh the contents of the view.
*/
@Override
public void doViewHtml() {
Shell shell = workbenchWindow.getShell();
FileDialog fileDialog = new FileDialog(shell,SWT.OPEN);
String filePath = fileDialog.open();
String htmlContents = null;
if(filePath != null)
htmlContents = HtmlFileReader.fetchHtmlContents(filePath);
firePropertyChange(ACT_IMPORT_FILE, null, htmlContents);
}
...
}
RAP片段抽象方法的实现与RCP不同。 它使用“上载”小部件将HTML文件传输到Web服务器,然后将其打开,如清单7所示:
public class ViewHtmlAction extends AbstractViewHtmlAction {
...
/**
* Opens a new shell for uploading a HTML file,
* creates the widgets.
*/
@Override
public void doViewHtml() {
Display display = Display.getDefault();
Shell shell = new Shell(display, SWT.PRIMARY_MODAL
| SWT.CLOSE | SWT.RESIZE);
shell.setText("Upload a HTML file");
shell.setLayout(new GridLayout());
shell.setSize(450, 60);
// Creates the control in the shell.
createControl(shell);
shell.layout();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
}
/**
*
* @param shell
*/
protected void createControl(final Shell shell){
Upload upload = new Upload(shell,SWT.NONE,Upload.SHOW_UPLOAD_BUTTON);
upload.setUploadButtonText("Upload");
upload.setBrowseButtonText("Location...");
GridDataFactory.fillDefaults().grab(true, false).applyTo(upload);
upload.addUploadListener(new UploadListener(){
...
...
});
}
...
}
RAP平台提供了会话单例,用于访问会话范围内的唯一实例。 该示例说明了在RAP中使用会话单例以及在RCP中使用公共单例的情况。
ExampleSingleton
的单例类。 还创建了一个名为ISingletonProvider
的接口和一个名为ImplementationLoader
的类加载器。 public class ExampleSingleton {
private final static ISingletonProvider PROVIDER;
static{
PROVIDER = (ISingletonProvider) ImplementationLoader
.newInstance(ExampleSingleton.class);
}
/**
* Gets the instance of ExampleSingleton
which has
* different implementations in RAP and RCP fragment.
* @return
*/
public static ExampleSingleton getInstance(){
return (ExampleSingleton)PROVIDER.getInstanceInternal();
}
public String fetchSingtonInfo(){
return PROVIDER.fetchSingletonInfo();
}
}
public interface ISingletonProvider {
Object getInstanceInternal();
/**
* Fetches the singleton info,which is different
* between RCP platform and RAP platform.
* @return
*/
String fetchSingletonInfo();
}
public class ImplementationLoader {
public static Object newInstance(final Class> type){
String name = type.getName();
Object result = null;
try {
result = type.getClassLoader()
.loadClass(name + "Impl").newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
ExampleSingleton
子类。 在RAP和RCP片段中都实现ISingletonProvider
接口,以提供不同的单例实现。 public class ExampleSingletonImpl implements ISingletonProvider {
public Object getInstanceInternal() {
return SessionSingletonBase.getInstance(ExampleSingleton.class);
}
...
...
}
public class ExampleSingletonImpl implements ISingletonProvider {
private static ExampleSingleton singleton;
/* (non-Javadoc)
* @see com.ibm.msdk.example.singleton
* .ISingletonProvider#getInstanceInternal()
*/
@Override
public Object getInstanceInternal() {
if(singleton == null)
singleton = new ExampleSingleton();
return singleton;
}
/* (non-Javadoc)
* @see com.ibm.msdk.example.singleton
* .ISingletonProvider#fetchSingletonInfo()
*/
@Override
public String fetchSingletonInfo() {
return "This message is from RCP fragment!";
}
}
在本部分中,您将制作一个WAR文件,将该文件部署到Tomcat,并了解一些有关部署的WAR文件不起作用的故障排除提示。
当前,Eclipse不为构建RAP应用程序提供直接支持。 现在,您需要使用多个Ant脚本和资源模板制作WAR文件。 RAP的CVS中的org.eclipse.rap.demo.feature显示了如何创建将org.eclipse.rap.demo项目打包为RAP应用程序的WAR文件。 您可以对其进行修改,并使功能项目可用于HTML查看器示例。
com.ibm.msdk.example.rap.feature
,然后将以下内容添加到功能列表中( 如图6所示 ):
如果不需要RAP演示插件,请从功能列表中删除org.eclipse.rap.demo。
com.ibm.msdk.example.rap.feature
, 如图6所示: com.ibm.msdk.example.rap.feature
。 BUILD SUCCESSFUL
消息。 请注意,从进度指示器来看,PDE导出任务仍在后台运行。 等待直到完成。
File file = new File( "build\\demo\\WEB-INF\\eclipse\\plug-ins" )
#Eclipse Runtime Configuration File
osgi.bundles= com.ibm.icu.base@start,\
com.ibm.msdk.example.rap,\
com.ibm.msdk.example@start,\
org.apache.commons.fileupload@start,\
org.apache.commons.io@start,\
org.eclipse.core.commands@start,\
org.eclipse.core.contenttype@start,\
org.eclipse.core.databinding.observable@start,\
org.eclipse.core.databinding.property@start,\
org.eclipse.core.databinding@start,\
org.eclipse.core.expressions@start,\
org.eclipse.core.jobs@start,\
org.eclipse.core.runtime@start,\
org.eclipse.equinox.app@start,\
org.eclipse.equinox.common@2:start,\
org.eclipse.equinox.http.registry@start,\
org.eclipse.equinox.http.servletbridge@start,\
org.eclipse.equinox.http.servlet@start,\
org.eclipse.equinox.preferences@start,\
org.eclipse.equinox.registry@start,\
org.eclipse.help@start,\
org.eclipse.osgi.services@start,\
org.eclipse.rap.demo@start,\
org.eclipse.rap.jface.databinding@start,\
org.eclipse.rap.jface@start,\
org.eclipse.rap.rwt.q07,\
org.eclipse.rap.rwt@start,\
org.eclipse.rap.ui.views@start,\
org.eclipse.rap.ui.workbench@start,\
org.eclipse.rap.ui@start,\
org.eclipse.rwt.widgets.upload@start,\
org.eclipse.equinox.servletbridge.extensionbundle
osgi.bundles.defaultStartLevel=4
@start
。
要将sample.war文件部署到Tomcat,您需要将sample.war复制到{TOMCAT_HOME} / webapps /。 启动Tomcat,并使用http:// localhost:8080 / sample / msdkExample访问HTML查看器, 如图8所示:
您可能会遇到一种情况,即RAP在开发时正在运行,但是在将其部署到Tomcat或WebSphere之后却无法正常工作。 如果遇到这种情况,请检查以下内容:
commandline
-console
enableFrameworkControls
true
在控制台中键入ss
(例如Tomcat),然后查看是否所有捆绑软件都已启动。 如果不是,请尝试使用start
启动它们。 堆栈跟踪可能会暗示丢失了什么。 确保ss列表中有一个状态为RESOVLED
的org.eclipse.equinox.servletbridge.extensionbundle
, 如图9所示:
javax.servlet
捆绑包。 在插件清单中,必须在Import-Package
部分而不是Require-Bundle
列出javax.servlet
。 org.eclipse.update.configurator
软件包。 *.jetty.*
捆绑包。 本文介绍了RAP和RCP应用程序开发的单源概念。 您学习了如何使用单源技术将现有RCP应用程序转换为基于Web的RAP应用程序。 RAP为RCP开发人员提供了强大的工具,可以重用您现有的代码库来创建基于Web的应用程序。 本文还提供了一种将RAP应用程序打包到WAR文件的方法,并展示了如何将其部署到Web容器。
翻译自: https://www.ibm.com/developerworks/web/library/wa-rcprap/index.html
rap开发与rcp开发