top
Loading...
EclipseRCP+Spring建胖客戶端Web程序
摘要 Eclipse豐富的客戶端平臺(RCP)正在快速地成為構建胖客戶端應用程序的框架選擇。本文將向你詳細介紹如何利用Eclipse RCP進行Spring Web開發。

一. 引言

盡管Web 2.0和豐富的因特網應用程序(RIA)如今極為風行,但是,當你真正需要胖客戶端功能時構建一個豐富的Web前端可能并不真正滿足你的要求。

但是,如果你確實想避開所謂RIA狂熱而選擇一種實際的胖客戶端解決方案的話,那么你該怎樣做呢?回答是:你可以選擇一種豐富的客戶端平臺(RCP)來為你處理大多數的工作。實質上,這種RCP概念為Java桌面應用程序世界提供了一種新型的框架。

一個RCP提供了一個應用程序的框架/外殼,還有一組基于模塊的API,你能夠基于這一外殼來構建自己的應用程序。這個RCP負責實現所有的繁重任務,例如添加菜單,工具條,不同的視圖等等,而你就不必再重復工作。

本文將引導你詳細地構建一個胖客戶端接口以連接到在上一篇文章中構建的服務器上。你將基于Eclipse豐富的客戶端平臺來構建胖客戶端,然后把Eclipse RCP與Spring集成到一起。

【準備工作】

·Eclipse 3.1.2

·MyEclipse 4.1.1

·Java SE 5

·一個Servlet容器或J2EE服務器(本文使用的是Tomcat 5.5+)

·Spring 1.2+

二. 為什么使用Eclipse RCP?

如今已經有越來越多的應用程序基于Eclipse RCP進行開發(當然,還有Eclipse厚實的開發背景),所以,我們可以安全地假定,與任何其它框架相比,這種框架已經得到更為廣泛的測試。

下面,讓我們開始。

(一) 創建一個新的Eclipse插件工程

請按照下列步驟為你的豐富的客戶端應用程序創建一個新的Eclipse插件工程:

1. 在Eclipse中創建一個新的插件工程,并命名工程為EclipseTradeClient。把這個插件的應用目標定位在Eclipse 3.1版本,并且確保點選了"Create an OSGi bundle manifest"(見圖1),并點擊Next。


圖1."New Plug-in Project"對話框在Eclipse中創建一個新的插件工程EclipseTradeClient。

2. 在"Plug-in Content"屏幕上,保持默認設置,但是確保選擇了"Yes"-創建一個豐富的客戶端應用程序(見圖2),并點擊Next。


圖2.在"Plug-in Content"屏幕選擇創建一個豐富的客戶端應用程序。

·至于模板,選擇"RCP application with a view",并點擊Next。

·填寫顯示如圖3的RCP應用程序屬性,并點擊Finish。之后,你將被提示轉到"Plug-in Development"視圖下,并點擊Yes。


圖3.RCP插件工程向導最后的結果屏幕

·現在,你已經創建了你的工程,再打開plugin.xml。你將看到如下圖4所示的屏幕快照。

點擊放大此圖片
圖4.Plugin.XML概要

如果你是Eclipse插件開發的新手,你可能經常需要使用底部的plugin.xml選項卡。正如你從Overview選項卡中所看到的,你可以運行/調試你的Eclipse豐富的客戶端應用程序。

·展開EclipseTradeClient/src/eclipseTradeClient包來觀察Eclipse的RCP向導為你創建的類。在Eclipse編輯器中,點擊"All Extensions"選項卡并且展開每一個頂級的結點,如圖5所示。

點擊放大此圖片
圖5.Eclipse生成的類及所有的擴展

請注意一下你的Application類,Perspective類和View類的擴展入口。既然Eclipse的豐富的客戶端平臺包括plugin.xml文件,所以你可以簡單地添加新的組件-通過"Extensions"選項卡中的"Add..."按鈕來添加它們。

(二) 重構默認的View類

如你所見,Eclipse向導為你創建了一個稱為View的類。并不是很有用,對嗎?請使用如下步驟來重構默認的視圖類:

1. 讓我們重命名它-右擊Package Explorer中的View.java。轉到Refactor->Rename,輸入新名為ExplorerView并且點擊Preview。在隨后彈出的面板上,你會看到Perspective類被重構-使用ExplorerView.ID來代替View.ID(見圖6)。點擊OK。

點擊放大此圖片
圖6.為ExplorerView重構View類

2. 遺憾的是,Eclipse的重構能力有點弱-特別與IntelliJ作比較的話。對于象這樣的重構來說,IntelliJ將不僅按期望對類加以改變,而且它會把重構應用于你的.xml文件!這是非常有用的特征,特別是在一種Spring/Hibernate/XML配置操作比例極大的情況下。

你必須手工地更新對plugin.xml的重構。打開plugin.xml,并且點擊plugin.xml選項卡。找到相應于View的擴展,并且作如下更新:

name="ExplorerView"
class="eclipseTradeClient.ExplorerView"
id="EclipseTradeClient.explorerView">

此后,進行保存(見圖7)。


圖7.進一步重構-手工更新Plugin.XML

3. 對于這種簡單的重構,情況就是這樣,對嗎?是的;但遺憾的是,你還沒有結束。打開類ExplorerView,改變靜態變量ID-把它初始化為EclipseTradeClient.explorerView。這相應于你剛才在plugin.xml中設置的ID。

4. 最后,你完成重構。現在,讓我們測試一下是否一切改動正常。切換回編輯器中的plugin.xml,并且點擊"Overview"選項卡。點擊"Launch an Eclipse application",這應該導致如圖8所示結果。


圖8.啟動Eclipse Trade Client程序

5. 現在讓我們改變結點的名字。打開類ExplorerView。找到內部類ViewContentProvider,并且改變方法"Object getElements(Object parent)",讓其返回一個字符串數組({"Watch List","Order History"})。



三. 把Spring Remoting添加到你的應用程序

下面,我們把Spring添加到你的Eclipse豐富的客戶端以便它向前一篇文章中的StockTradeServer工程發出請求。

首先,當開發Eclipse插件/RCP應用程序時,添加第三方庫的推薦的方法是通過另外一個插件。這樣做以后,你就不需要把這些第三方jars添加到你創建的每個工程。而是,你僅建立你的插件/RCP工程和第三方庫工程之間的某種依賴性。首先,我們假定你熟悉Eclipse的classloader。要點是,你必須采取一些額外的步驟來確保你的類在插件依賴性之間能夠彼此找到對方:

1. 在Eclipse中創建一個新的插件工程。并命名這個新工程為SpringClient。然后,設置如下值:

ID = SpringClient
Class = springClient.SpringClientPlugin

在填充Plug-in屬性后,點擊Finish。對于SpringClient插件工程,你不需要任何模板,因為其主要目的是存儲Spring庫和任何Spring相關的服務類。

2. 在你的解壓的spring-framework-1.2.8發行包中,你會找到下列jar文件:

·spring-aop.jar-在文件夾dist下

·spring-beans.jar-在文件夾dist下

·spring-context.jar-在文件夾dist下

·spring-core.jar-在文件夾dist下

·spring-remoting.jar-在文件夾dist下

·commons-logging.jar-在文件夾libjakarta-commons下

·log4j-1.2.13.jar-在文件夾liblog4j下

然后,把它們全部復制到你的SpringClient根目錄下。

3. 在Eclipse的包資源管理器中,右擊SpringClient以打開工程屬性。選擇"Java Build Path",點擊"Libraries"選項卡,并且把剛才你通過按鈕"Add JARs"添加的所有的那些jar文件加入。請確保你也導入了這些庫!點擊"Order and Export"選項卡,并且檢查所有的庫(見圖9)。通過這樣做,你就可以確保,當你創建對SpringClient的一種工作依賴性時,spring和log jars也是可用的。此后,點擊OK。


圖9.輸出第三方庫

4. 現在,你要修改SpringClient的manifest。在包資源管理器中,展開SpringClient->META-INF并且打開MANIFEST.MF。點擊"Runtime"選項卡并且點擊Classpath部分的"Add"。全選Spring jars和logging jars并且點擊OK。現在,在"Exported Packages"節中,點擊Add。選擇所有的包以便導出,并點擊OK(見圖10)。


圖10.把第三方庫添加到插件Classpath并導出包

我以前提及過,Eclipse的classloader經常引起問題。為了補救這一點,你可以點擊MANIFEST.MF選項卡并且添加下面一行:

Eclipse-BuddyPolicy: registered

5. 現在,讓我們添加spring配置文件。在Package Explorer中,轉到src目錄,創建一個新文件applicationContext.xml,并且加入下列內容:



在src目錄下,另外創建一個新文件beanRefFactory.xml并且加入下列內容:



不必感到驚訝,這些配置文件與你對stocktradeserver工程進行單元測試時使用的spring配置文件是相同的,除了你重命名了applicationContext.xml以外。

6. 為了簡化問題,你可以把類從stocktradeserver工程復制到SpringClient的src目錄下。在SpringClient的src目錄下面,創建包stephenlum.services.stock和stephenlum.services.stock.dto。

如果你還沒有準備好,你可以下載本文源碼或參考我的前一篇文章并且復制stephenlum.services.stock下的類StockService.java。然后,復制在stephenlum.services.stock.dto下的類StockDTO.java(見圖11)。


圖11.完成上面操作后的Package Explorer看上去的樣子

7. 把代碼添加到類SpringClientPlugin以裝載Spring的應用程序上下文。注意,你要把該代碼添加到構造器中。下面是新的SpringClientPlugin類:

package springClient;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.beans.factory.access.SingletonBeanFactoryLocator;
/**
*應用于桌面的主插件類。
*/
public class SpringClientPlugin extends AbstractUIPlugin {
private BeanFactory beanFactory;
//共享實例.
private static SpringClientPlugin plugin;
/**
*構造器.
*/
public SpringClientPlugin() {
plugin = this;
BeanFactoryLocator beanFactoryLocator = SingletonBeanFactoryLocator.getInstance();
BeanFactoryReference beanFactoryReference = beanFactoryLocator.useBeanFactory("ctx");
beanFactory = beanFactoryReference.getFactory();
}
/**
*在插件激活時調用這個方法
*/
public void start(BundleContext context) throws Exception {
super.start(context);
}
/**
*當停止插件時,調用這個方法
*/
public void stop(BundleContext context) throws Exception {
super.stop(context);
plugin = null;
}
/**
*返回共享實例.
*/
public static SpringClientPlugin getDefault() {
return plugin;
}
/**
*返回在給定的插件相對路徑下的圖像文件的一個圖像描述符
* @param path-路徑
* @返回圖像描述符
*/
public static ImageDescriptor getImageDescriptor(String path) {
return AbstractUIPlugin.imageDescriptorFromPlugin("SpringClient", path);
}
public BeanFactory getBeanFactory() {
return beanFactory;
}
}

8. 最后,添加依賴性以實現工程EclipseTradeClient依賴于你的新插件工程SpringClient。在工程EclipseTradeClient中,打開plugin.xml并且點擊"Dependencies"選項卡。在"Required Plug-ins"節中,點擊Add,選擇"SpringClient(1.0.0)",并且點擊OK(見圖12)。


圖12.把SpringClient添加為一個要求的插件

現在,你必須在EclipseTradeClient manifest文件中添加與Eclipse的伙伴策略相關的內容。在文件plugin.xml中,點擊MANIFEST.MF選項卡并且添加下列入口:

Eclipse-RegisterBuddy: SpringClient

四. 創建一個新的WatchListView

現在,你可以開始創建你自己的視圖類了。首先,你要創建一個WatchListView,它將向應用程序服務器的StockDataService發出一個請求:

1. 在plugin.xml中,轉到extensions選項卡。

2. 在All Extensions樹中選擇org.eclipse.ui.views,然后點擊Add。

3. 隨后出現一個新的對話框窗口。在Extension Points樹中滾動并且選擇org.eclipse.ui.views。在相應于org.eclipse.ui.views的可用模板中,選擇SampleView,然后點擊Next(見圖13)。


圖13.新的擴展對話框

4. 在"Main View Settings"窗口中,填寫如下內容:

Java Package Name = eclipseTradeClient.views.watchlist
View Class Name = WatchListView
View Name = Watch List View
View Category ID = EclipseTradeClient
View Category Name = WatchList Category

讓"Table Viewer"保持選擇狀態并且點選"Add the view to the resource perspective checked"(見圖14)。點擊Next。


圖14.針對于Watch List視圖設置"Main View Settings"

5. 在"View Features"下,保持默認設置并且點擊Finish。

6. 現在,你會在plugin.xml的"All Extensions"選項卡中看到新的"View and Category"。

7. 現在,你可以開始編寫你的Watch List視圖了。這個觀察列表是一個表格,因此首先要為此表實現接口ITableLabelProvider。在包eclipseTradeClient.views.watchlist下創建一個新類WatchListTableLabelProvider。你可以把一個ITableLabelProvider當作是JFace的等價物-Swing中的TableCellRenderer。下面是WatchListTableLabelProvider的代碼部分:

package eclipseTradeClient.views.watchlist;
import java.text.NumberFormat;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import stephenlum.services.stock.dto.StockDTO;
public class WatchListTableLabelProvider extends LabelProvider implements
ITableLabelProvider {
private static NumberFormat numberFormat = NumberFormat.getInstance();
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
public String getColumnText(Object element, int columnIndex) {
if (element != null) {
switch (columnIndex) {
case 0:
return ((StockDTO) element).getTickerSymbol();
case 1:
return ((StockDTO) element).getLastTrade().toString();
case 2:
return numberFormat.format(((StockDTO) element).getVolume());
case 3:
return ((StockDTO) element).getDaysRange();
case 4:
return numberFormat.format(((StockDTO) element).getAvgVol());
case 5:
return ((StockDTO) element).getDaysRange();
case 6:
return ((StockDTO) element).getFiftyTwoWeekRange();
case 7:
return ((StockDTO) element).getMarketCap();
}
}
return "";
}
}

8. 最后,你把你的WatchListView添加到Perspective類。在Package Explorer中打開類Perspective并且作如下修改以便WatchListView將出現于該頁面的底部:

package eclipseTradeClient;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;
import org.eclipse.ui.IFolderLayout;
import eclipseTradeClient.views.WatchListView;
public class Perspective implements IPerspectiveFactory {
public void createInitialLayout(IPageLayout layout) {
String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(false);
layout.setFixed(false);
layout.addStandaloneView(ExplorerView.ID,
false,
IPageLayout.LEFT,
0.25f,
editorArea);
IFolderLayout topLeft = layout.createFolder("TOP",
IPageLayout.TOP,
0.50f,
editorArea);
layout.addView(WatchListView.ID,IPageLayout.BOTTOM, 0.25f,editorArea);
}
}

9. 現在,你可以在類WatchListView中進行添加。我盡量保持模板生成的代碼不動以便于你可以自由地添加你的代碼。實質上,你是在添加一個表格-它將顯示包含在一個類StockDTO實例中的所有信息。因此,表格中的列也是基于StockDTO的成員。我已經重命名了兩個生成的Action-現在action1能夠從stocktradeserver中取回股票的列表并且在表格中顯示它們,而action2從表格中刪除所有元素(請參考源碼中的列表1.eclipseTradeClient.views.watchlist)。

五. 運行應用程序

現在,你可以運行你的應用程序了。如果還沒有準備好的話,你可以把stocktradeserver工程按如下步驟導入到Eclipse:

1. 在Eclipse中,點擊工具欄按鈕"Deploy MyEclipse J2EE project to Server"(見圖15)。


圖15.發布MyEclipse J2EE服務器按鈕

確保在列表下的工程是stocktradeserver。點擊Add,選擇Tomcat 5作為你的服務器,并且點擊Finish。當你看到一條消息"Successfully deployed"時,點擊OK(見圖16)。


圖16.StockTradeServer被成功發布

現在,啟動Tomcat服務器(見圖17)。Tomcat應該會成功地啟動。


圖17.通過MyEclipse插件啟動Tomcat

2. 啟動"Eclipse Rich Client"。打開EclipseTradeClient's plugin.xml文件,點擊"Overview"選項卡,并且點擊"Launch an Eclipse application"。當應用程序啟動時,按下圖18中的紅色按鈕以得到一個股票列表。這一行為將使用Spring HttpInvoker從應用程序服務器取回股票列表。你可以按下紅色圓圈右邊的按鈕來清除股票列表(見圖18)。


圖18.EclipseTradeClient成功運行

一切順利!你已經成功構建了一個小型的Eclipse豐富的客戶端程序并且使用Spring remoting技術把它連接到一個應用程序服務器上。

六. 小結

總之,基于Eclipse RCP構建你的胖客戶端程序將會大大減少構建這種程序的GUI框架所需的繁重代碼。另外,通過把Spring remoting用作客戶端/服務器通訊機制還允許你輕松地實現協議的切換,同時還提供其它所有在服務器端的Spring優點。
作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗