開始之前
本教程演示如何使用 OpenLaszlo 平台和 Web 服務來開發、打包和 部署一個已編寫好的富 Internet 客戶機。富客戶端利用了後端的服務(這些後端服務是 通過使用 SOAP Web 服務的通用 SOA 方法提供)。還將了解如何有效地使用 Eclipse Laszlo IDE 和 Eclipse Web Tools 來使得開發更加容易且富有生產效率。
關於 本教程
由於大多數 Web 應用程序都構建於 HTML 和 HTTP 之上,所以 Web 對於 用戶經常使用的應用程序(比如拍賣和書店站點)來說是一個很好的平台。但是,該例不 適合需要豐富用戶界面的業務應用程序,因為缺少狀態、組件數量有限且浏覽器不一致。
如果不是 HTML 和 HTTP,那會是什麼呢?富 Internet 客戶機(Rich Internet Clients,RIC)也稱為富 Internet 應用程序(Rich Internet Applications,RIA), 是下一代 Web 應用程序。RIC 提供客戶機/服務器應用程序的可用性、響應性和重用,以 及傳統 Web 應用程序的部署、可管理性和可用性。
本教程探索創建富 Internet 應用程序、FluidMotion 和使用 OpenLaszlo 平台。
前提條件
您應該具備一些基本的 Java™、Web 開發和 XML 技能。 對 Web 服務、XPath 和持久存儲的基本了解是有幫助的,但不是必需的。
系統需求
需要安裝了以下軟件:
Java Development Kit (JDK)™ V1.4 或更高版本
Apache Tomcat V5.0.28
還需要下載以下軟件(本教程解釋了如何安裝和配置它):
OpenLaszlo V3.0.2
Eclipse Web Tools all-in-one 0.7.1
IDE for Laszlo V2.1
OpenLaszlo
本節詳細介紹 OpenLaszlo,包括它如何適合 Java 2 Platform, Enterprise Edition (J2EE™) 空間,以及可用的開發工具。
概 述
OpenLaszlo 是一個開放源碼的富客戶機平台,用於開發動態數據驅動的應用程 序。為了運行在 Macromedia Flash 中的、面向對象的、事件驅動的用戶界面(UI),它 結合了 XML、JavaScript™ 和 XPath。它包括一組豐富的組件和服務(稱為運行時 框架)和一個用於集成的可選 Java servlet。
OpenLaszlo 在公開的 Common Public License 下可用。這是一種流行的許可,因為 除了常見的授予使用和修改源代碼的權限以外,它還提供商業發行版。這意味著商業產品 可以派生自 OpenLaszlo 平台。
其他富客戶機
Asynchronous Java and XML (Ajax) 對於結合諸如異步 JavaScript、XML、XHTML 和 CSS 之類的標准 Web 技術 的舊技術來講是一個新術語。有了這一新技術,隨之出現了許多有競爭力的框架/工具箱 。至於哪種框架/工具箱將成為標准仍然未可知。但是這一技術無疑正在不斷流行, Google 的威力在一定程度起到了推波助瀾的作用。
Macromedia Flex 是一款商業產品,用於開發運行在 Flash 播放器中的業務應用程序 。許多 Web 游戲和電影也利用了 Flash 播放器。Flex 應用程序是用 Maximum Experience Markup Language (MXML) 編寫的,並且也使用 ActionScript 進行事件和流 控制。MXML 是一種基於 XML 的語言,用於定義 UI。
OpenLaszlo 是本教程的焦 點,它是 Flex 開放源碼的替代物。與 Flex 一樣,它運行在 Flash 播放器中,使用 XML 來定義 UI,並使用腳本語言進行事件和流控制,以及用服務器端代碼進行數據集成 。
OpenLaszlo 用於布局用戶界面的 XML 格式叫做 Laszlo XML (LZX)。 OpenLaszlo 包含一個編譯器,用於將 LZX 和 JavaScript 編譯成二進制 Shockwave Flash (SWF) 文件,Flash 播放器將呈現該文件。
運行在 Flash 播放器中是理想 的,因為它是一個到處存在的平台。Macromedia 宣稱它存在於 96% 連接到 Internet 的計算機上。沒有哪個單個的浏覽器可以這樣宣稱。不斷地,它也成為在許多其他設備( 比如手提計算機)上可用。Flash 播放器也使得安裝比較容易,因為它自動地取得應用程 序的最新版本,並自動地更新它自己。甚至,Flash 可以用於產生吸引眼球的應用程序, 因為它還是用於開發基於 Web 的游戲和電影的平台。那麼為什麼不直接使用 Flash 工具 呢?Flash 使用一種具有時間線和幀的電影手法(metaphor),這使得它難以構建業務應 用程序。但是,OpenLaszlo 使用一種具有表、樹和組件的常見應用程序框架手法,這是 業務應用程序開發人員所熟悉的方法。
OpenLaszlo 如何進入 J2EE
OpenLaszlo 作為客戶機層的另一個表示方案,完美地進入 J2EE 堆棧,如圖 1 所示。
圖 1. OpenLaszlo 作為 J2EE 堆棧的一部分
使用以下三種協議之一,OpenLaszlo 可以通過 HTTP 與後端服務通信。這三種協議是 :JavaRPC、eXtensible Markup Language -- Remote Procedure Call (XML-RPC) 和 SOAP。JavaRPC 允許調用服務器端 Java 方法。XML-RPC 和 SOAP 是基於標准的 Web 服 務協議,支持以獨立於語言的方式通過 HTTP 調用遠程過程。
如果您不需要 J2EE 應用服務器的所有強大功能,OpenLaszlo 應用程序可以運行在包 含的 Laszlo Presentation Server (LPS) 上,這是 Apache Tomcat 的定制版本,或者 運行在諸如 Apache or Microsoft Internet Information Server (IIS) 的基本 Web 服 務器上,這稱為 Standalone OpenLaszlo Output (SOLO)。
開發工具
要開始構建 Laszlo 應用程序,需要用到 OpenLaszlo Development Kit (OLDK)。 OLDK 包含構建 OpenLaszlo 應用程序所需用到的任何東西,包括 LPS、運行時組件和編 譯器,以及很多很好的文檔、演示和示例代碼。
除了 OLDK 之外,我們還推薦使用 IDE for Laszlo。它是一個 Eclipse 插件,其中 包括很多好的特性,比如 Laszlo 項目和文件向導、一個 Laszlo Perspective 以及一個 可視化設計器和調試器。當前,IDE for Laszlo 是一個 IBM alphaWorks 項目。但是, IBM 和 Eclipse Foundation 最近宣布,IBM 將捐出 Eclipse Technology Projects 的 代碼基。
IDE for Laszlo 構建在 Eclipse Web Tools Platform (WTP) 之上。這是理想的情況 ,因為 WTP 旨在構建標准(HTML、XML、CSS)和基於 J2EE 的 Web 應用程序。建立在 WTP 基礎之上,IDE for Laszlo 具有開發多層應用程序所需的所有工具。後面就會看到 ,WTP 也支持開發 Web 服務。
FluidMotion 架構
本教程中給出的 FluidMotion 應用程序是一個簡單的 Work Order Management (WOM) 應用程序,允許雇員向數據庫提交新的工作單。WOM 應用程序 允許組織收集及管理工具和設備維護請求,通過確保請求不被忘記並及時完成,而為組織 帶來價值。本教程中的 FluidMotion WOM 允許維護人員查看列表中的工作單,並在完成 後更新和關閉它們。
圖 2 中所示的 FluidMotion 應用程序架構包括客戶機和服 務器組件。客戶機是用 OpenLaszlo 富 Internet 客戶機框架編寫的,該框架由 Macromedia Flash Player 呈現,而後者宿主在 Web 浏覽器中。客戶機通過 SOAP 與通 過 Apache Axis 公開的 Web 服務進行通信,Apache Axis 是一個開放源碼的 Web 服務 框架。Web 服務然後使用 Hibernate(一個開放源碼的對象關系映射框架)將工作單持久 存儲到 Derby,Derby 是一個輕量級的 Java 數據庫。服務器組件宿主在 OpenLaszlo 服 務器上,該服務器是 Apache Tomcat 的一個擴展,而 Apache Tomcat 是一個開放源碼的 Web 容器。
圖 2. FluidMotion 應用程序架構
設置開發工具
從前一節已經看到,設置成功的 OpenLaszlo 開發環境需要用到 幾個軟件。本節解釋如何安裝和配置這些軟件。
OpenLaszlo Development Kit
OpenLaszlo Development Kit 帶有特定於平台的安裝程序,如果您的操作系 統不是顯式受支持的,則可以使用 Dev Kit。要在 Microsoft® Windows® 中安 裝開發工具箱,請執行以下步驟:
下載 openlaszlo-3.0.2-windows-dev-install.exe,如果還沒有下載的話。
雙擊 openlaszlo-3.0.2-windows-dev-install.exe。
閱讀許可,並通過單擊 I Agree 接受許可。
選擇一個目錄用於安裝 OpenLaszlo 服務器,並單擊 Install 。
單擊 Finish。
一完成安裝,LPS 就會立即啟動,您的默認浏覽器也會 啟動(如果還沒有打開的話)。浏覽器被定向到 OpenLaszlo 文檔、演示和示例代碼的本 地版本。閱讀完本教程之後,請花點時間仔細閱讀該文檔,它很值得一讀。
Eclipse Web Tools
Eclipse Web Tools 依賴於 Eclipse V3.1 以及幾個 其他 Eclipse 項目:EMF、GEF 和 Java EMF Model。由於所有這些依賴項,所以有三種 安裝 WTP 的方案。如果已經安裝了 Eclipse V3.1,第一個選項就是獨立地下載所有其他 Eclipse 項目並分別安裝它們。另一種方案是使用 Update Manager 中預配置的 Eclipse.org 更新站點。
第三種方案是 all-in-one 軟件包,其中包括 Eclipse V3.1、WTP V0.7.1 和所有其他依賴項。如果還沒有安裝 Eclipse V3.1 的話,這是一個 首選方案。
提示:如果需要將 Eclipse 的多個版本安裝在同一台計算機上,那麼 將 Eclipse 解壓在 eclipse-3.1 目錄中是有幫助的。
要安裝 all-in-one 軟件 包,請執行以下步驟:
下載 wtp-all-in-one-0.7-win32.zip,如果還沒有下載的 話。
將 wtp-all-in-one-0.7-win32.zip 解壓到所希望的目錄。
通過在安 裝 WTP all-in-one 軟件包的目錄中雙擊 eclipse.exe 而啟動 Eclipse。
當提示 工作空間時,保持默認選項,然後單擊 OK。
提示:對於 Laszlo IDE,只需要 0.7 版本的 WTP。但是 0.7.1 版本在 Web 服務工具方面有了一些改進,並且在本教程的 以後各節中將用到這些增強。
IDE for Laszlo
安裝 WTP 之後,就來安裝 Laszlo IDE 插件。它們被打包成一個 .zip 軟件包,可以使用 Eclipse Update Manager 來安裝。
警告:要完成這些步驟,必須連接到 Internet。
要安裝 Laszlo IDE,請執行以下步驟:
下載 laszloIDE.zip,如果還沒有下載的話。
如 果 Eclipse 當前還沒在運行,則通過在安裝 WTP all-in-one 軟件包的目錄中雙擊 eclipse.exe 而啟動它。
選擇 Help > Software Updates > Find and Install。
在 Feature Updates 頁面上,選擇 Search for new features to install,然後單擊 Next。
在如圖 3 所示的 Update sites to visit 頁面上, 單擊 New Archived Site。
圖 3. Update Manager 向導中的 Update sites to visit 頁面
浏覽 並找到 laszloIDE.zip 文件,然後單擊 OK。
在 Edit Local Site 對話框中,通 過單擊 OK 確認 .zip 位置。
返回 Update sites to visit 頁面,選中 laszloIDE.zip,單擊 Finish。
在 Search Results 頁面上,選中 laszloIDE.zip,然後單擊 Next。
在 Feature License 頁面上,閱讀許可,並通 過選中 I accept the terms in the license agreement 接受許可,然後單擊 Next。
在 Installation 頁面上,單擊 Finished。
在 Feature Verification 頁面上,單擊 Install All。
當提示重新啟動時,單擊 Yes。
在 Eclipse 重新啟動後,WTP 和 Laszlo IDE 就已安裝好了,您就可以開始開發 Web 服務和 OpenLaszlo 客戶機了。
開發 Web 服務
在本節中,使用 Eclipse Web Tools 來為 OpenLaszlo 客戶機將會調用的 FluidMotion 應用程序構建一個基本的 Web 服務。該 Web 服務將使用 Hibernate 來將數據持久存儲到 Apache Derby 數據庫。首先 創建一個動態 Web 項目。然後將服務創建為一個 Plain Old Java Object (POJO),再運 行 Web 服務向導將它公開為一個 SOAP 服務。最後將它打包為一個 Web 應用程序。
注意:在開始開發 Web 服務之前,請確保任何 LPS 服務器都沒在運行。否則, Tomcat 服務器會出現 WTP 錯誤,因為它試圖綁定到端口 8080,而這是 LPS 服務器所使 用的端口。要關閉 LPS 服務器,請激活命令窗口,並按 Ctrl+C。
創建動態 Web 項目
Web 服務最終將被打包為 Web 應用程序,並部署到 Web 容器。所以首先創 建一個動態 Web 項目,該項目具有可部署的 Web 應用程序所必需的結構。換句話說,它 將包含一個 WEB-INF 目錄、WEB-INF/lib 目錄和一個 web.xml 文件。針對 FluidMotion 服務器將這個項目命名為 fms。
要創建動態 Web 項目,請執行以下步驟:
從 Eclipse 主菜單選擇 File > New > Project。
在 Select a wizard 頁面上,選擇 Web > Dynamic Web Project,然後單擊 Next。
在 Dynamic Web Project 頁面上,輸入項目名稱,然後單擊 Show Advanced。
單擊 New 以添加新的 Tomcat 服務器。
在 New Server Runtime 頁面上,選擇 Apache > Apache Tomcat v5.0,如圖 4 所示,並單擊 Next。
圖 4. 選擇 Apache Tomcat v5.0 運行時
使用 Browse 找到 Tomcat 安裝目錄。
接下來,從 JRE 列表選擇一個 JDK, 如圖 5 所示,並單擊 Finish。注意,Eclipse 默認情況下一般使用 Java Runtime Environment (JRE),但是 Tomcat 必須配置為使用 JDK,因為它需要編譯工具,以將 JavaServer Pages™ (JSPs) 轉換為 servlet。所以這裡確保配置並選擇了 JDK 運 行時。
圖 5. Tomcat 服務器配置
回到 Dynamic Web Project 頁面,單擊 Finish。
如果提示一個許可協定,就 閱讀它,並通過單擊 I Agree 接受它。
如果提示打開 J2EE 透視圖,則單擊 Yes 。
一旦完成 Dynamic Web Project 向導,您就在 Dynamic Web Projects 節點下 具有了一個新的動態 Web 項目,類似於圖 6 所示的項目。
圖 6. 新的動態 Web 項目的內容
創建 服務和數據轉移對象
創建 POJO 服務和數據轉移對象 (DTO) 與創建任何其他 Java 類是一樣的,只是有兩個細微差別。首先,Web 服務包含被很好地公開為數組的集 合。這使得描述服務的 Web Services Description Language (WSDL) 可以適當地處理復 雜類型。另外,並不是所有支持 Web 服務的語言都具有動態未類型化集合的概念。其次 ,DTO 必須具有無參構造函數,以便 XML 封送可以創建新的實例用於聯合。
清單 1 是下一節中公開為 Web 服務的 WorkOrderService 類。
清單 1. WorkOrderService 類
package com.ibm.laszlo.services;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.ibm.laszlo.dto.Building;
import com.ibm.laszlo.dto.Floor;
import com.ibm.laszlo.dto.WorkOrder;
import com.ibm.laszlo.util.HibernateUtil;
/**
* Service for work order management.
*/
public class WorkOrderService {
/**
* Finds a specific work order by id.
* @param id unique id of work order.
* @return work order.
*/
public WorkOrder findWorkOrderById(int id) {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
WorkOrder workOrder = (WorkOrder) session.get(
WorkOrder.class, new Integer(id));
tx.commit();
HibernateUtil.closeSession ();
return workOrder;
}
/**
* Returns all work orders.
* @return all work orders.
*/
public WorkOrder[] findAllWorkOrders() {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
List workOrders = session.createQuery("from WorkOrder").list();
tx.commit();
HibernateUtil.closeSession();
return (WorkOrder[]) workOrders.toArray(
new WorkOrder[workOrders.size()]);
}
/**
* Create a new work order.
* @param contact contact person's name.
* @param phone contact person's phone number.
* @param email contact person's email.
* @param description description of problem.
* @param building building problem is in.
* @param floor floor in building with problem.
* @param severity severity of the problem.
* @return new work order's id.
*/
public int createWorkOrder(String contact, String phone,
String email, String description,
String building, String floor, int severity) {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
WorkOrder workOrder = new WorkOrder(contact, phone,
email, building, floor, description, severity);
Date currentDate = new Date();
workOrder.setDateRequested(currentDate);
workOrder.setLastModified(currentDate);
workOrder.setStatus (WorkOrder.STATUS_REQUESTED);
session.saveOrUpdate (workOrder);
tx.commit();
HibernateUtil.closeSession ();
return workOrder.getId();
}
/**
* Collection of buildings and their floors.
* NOTE: Hard coded for simplicity but could be read from a
* database.
* @return
*/
public Building[] getBuildings() {
List buildings = new ArrayList();
Building building = new Building(1, "HQ");
building.addFloor(new Floor(1, "Floor 1"));
building.addFloor(new Floor(2, "Floor 2"));
building.addFloor(new Floor(3, "Mezzanine"));
buildings.add (building);
building = new Building(2, "Trump Tower");
building.addFloor(new Floor(1, "Trump 1"));
building.addFloor(new Floor(2, "Trump 2"));
building.addFloor(new Floor(3, "Trump 3"));
buildings.add(building);
return (Building[]) buildings.toArray(
new Building[buildings.size()]);
}
}
注意該類是如何具有五個方法的:findWorkOrderById()、 findAllWorkOrders()、createWorkOrder()、updateWorkOrder() 和 getBuildings()。 這五個方法將被公開為 SOAP 操作。還要注意,getBuildings() 和 findAllWorkOrders () 方法返回類型化數組而不是 java.util.List。該服務中引用的 WorkOrder、Floor 和 Building 類是帶有無參構造函數的簡單 JavaBeans。
注意,如果您的服務或 DTO 類使用任何類型的第三方庫,比如 WorkOrderService 類使用 Hibernate,那麼這些庫的 JAR 需要包含在 WebContent/WEB-INF/lib 目錄中。
將 POJO 服務公開為 Web 服 務
既然有了一個 POJO 服務,就將它公開為 Web 服務。這叫做自底向上的方法, 意味著從一個 Java 類開始,並使用它來生成描述該方法的 WSDL。替代方案是自頂向下 的方法,即從 WSDL 開始,並從它生成 Java 代碼。
要將 WorkOrderService 公 開為 SOAP Web 服務,請執行以下步驟:
從 Eclipse 主菜單選擇 File > New > Other。
在 Select a wizard 頁面上,選擇 Web Services > Web Service,然後單擊 Next。
在如圖 7 所示的 Web Services 頁面上,選中 Generate a proxy、Test the Web service 和 Monitor the Web service,然後單擊 Next。
圖 7. 生成 Web 服務的選項
在 Object Selection 頁面上,選擇您想要公開為 Web 服務的 bean,比如 WorkOrderService,然後單擊 Next。
在 Service Deployment Configuration 頁 面上,直接單擊 Next。這些配置就是針對將 Apache Axis JARs 添加到哪個項目的。此 外,它還會創建一個新項目,以允許您測試自己的 Web 服務,而不必具有 Laszlo 客戶 機。
如圖 8 所示,Web Service JavaBean Identity 頁面上的所有默認選項都應 該保持,所以單擊 Finish。該頁面允許您顯式地選擇哪些方法將由 WSDL 公開,以及使 用的 SOAP 風格。
圖 8. 針對公開方法和定義風格的配置
完成 Web 服務向導之後,就發生了幾件事情。首先,用相同名稱創建了一個新 的動態 Web 項目,並且客戶機被附加到它的末尾。該項目包含您的 Web 服務的一個消費 者以及一個基於 JSP 的測試工具,如圖 9 所示。這個測試客戶機是很方便的,因為測試 您的 Web 服務正確工作不需要完成 OpenLaszlo 客戶機。
圖 9. Web 服務測試客 戶機
其次,如果 Tomcat 服務器還沒有啟動,那麼服務器啟動並被添加到服務器視圖(參 見圖 10),用於管理應用程序的啟動、停止和重新部署。
圖 10. Tomcat 服務器 在運行
第三,兩個動態 Web 項目都被部署到 Tomcat 服務器,並且您可以開始通過基於 Web 的客戶機來測試服務。一個內部 Eclipse 浏覽器自動打開到測試頁面。
最後,配 置了一個 TCP/IP 監視器,如圖 11 所示,以便您可以監視測試客戶機與您的 Web 服務 之間的 SOAP 流量。
圖 11. TCP/IP 監視器監視客戶機與 Web 服務之間的流量
打包 Web 服務
在使用測試客戶機測試了 Web 服務之後,就可以將服務打包為 標准的 Web 應用程序或 .war 文件了,以將它部署到 Web 容器上。對於開發 OpenLaszlo 客戶機來說,尤其如此。前一節中由 Eclipse 自動啟動的 Tomcat 服務器和 您需要用於開發客戶機的 OpenLaszlo 服務器都運行在端口 8080 上。您需要打包 Web 服務,以便它可以被部署到 OpenLaszlo 服務器。
要打包 Web 服務,請執行以下 步驟:
從 Eclipse 主菜單選擇 File > Export。
選擇 WAR file,並 單擊 Next。
在 WAR Export 頁面上,選擇包含 Web 服務和生成的目的 .war 文 件的 Web 模塊,並單擊 Next。
警告:在啟動 OpenLaszlo 服務器之前停止由 Eclipse 啟動的 Tomcat 服務器。
要將 Web 服務部署到 OpenLaszlo 服務器,請 執行以下步驟:
將 .war 文件 fms.war 復制到 <OpenLaszlo Server>/Server/tomcat-5.0.24/webapps 目錄。
啟動 OpenLaszlo 服務器。
注意:將 Web 服務部署到 OpenLaszlo 服務器之後,到 WSDL 的 URL 是 http://localhost:8080/fms/wsdl/WorkOrderService.wsdl。
開發富客戶機
本節演示如何配置 Laszlo IDE 工作空間、創建新的 Laszlo 項目以及啟動 Laszlo 服務器。關於開發方面,它介紹了利用 Laszlo 組件、事件腳本編程、數據綁定 、調試、在 IDE 中運行應用程序,以及打包。
配置 Laszlo IDE —— 特定於工作空間
配置 Laszlo IDE 是特定 於工作空間的。參見圖 12 所示的 Eclipse Preferences 窗口。可以通過從 Eclipse 主 菜單選擇 Window > Preferences 而到達配置面板。Laszlo IDE 必須被配置為從 IDE 運行 Laszlo 應用程序。主要的要求是指定 LPS Web Root、Context Root 和應用服務器 端口(Apache Tomcat)。LPS Web Root 是 Laszlo 服務器的安裝實例所駐留的地方,並 需要指向 Context Root。圖 12 中定義的端口是 Apache Tomcat servlet 容器所監聽的 默認端口。默認的設計視圖和首選設置是 Local Design View。它使得編輯組件屬性更加 容易。可選地,Live Design View 可以被啟動為用於編輯的默認視圖。一個浏覽器選項 可以用於從 IDE 啟動應用程序。
圖 12. Laszlo IDE 配置面板
創建 Laszlo 項目
在可以開始開發 Laszlo 工件之前,需要創建一個項目用於容納它們。要創建 Laszlo 項目,請執行以下步驟:
從 Eclipse 主菜單選擇 File > New > Project。就會出現新建項目向導,如 圖 13 所示。
圖 13. New Laszlo Project 向導
選擇向導類型 Laszlo Project,然後單擊 Next。
輸入項目名稱,並單擊 Next,如圖 14 所示。
圖 14. 命名新的 Laszlo Project 向導
定義定制的 LPS 選項,如圖 15 所示,並單擊 Finish。
圖 15. Laszlo Project LPS 設置
一旦完成 Laszlo Project 向導,您就會被提示切換到 Laszlo 透視圖。然後就會創 建一個類似於圖 16 所示的新項目。
圖 16. 新的 Laszlo 項目
注意,在圖 16 中,新的 Laszlo 項目包含兩個組件庫。
創建了 Laszlo 項目之後,您就可以開始添加 Laszlo 或 LZX 文件了。要創建新的 Laszlo 文件,請執行以下步驟:
如果已經在 Laszlo 透視圖中,則從 Eclipse 主菜單選擇 File > New > Laszlo File。
如圖 17 所示,輸入一個與您的項目相對的容器目錄、一個文件名和一個文件類型( 對於可視化頁面就是 Canvas,對於 Laszlo 類的集合就是 Library)、組件和/或工具。
圖 17. 新建 Laszlo 文件向導
一旦完成新建 Laszlo 文件向導,您的項目就將包含一個類似於下面的新文件:
<?xml version="1.0" encoding="UTF-8" ?>
<canvas>
</canvas>
注意,這是一個 .xml 文件,其中包含兩個 canvas 標記,它們是可視化組件的容器 。在本教程的後面,您將使用這個新文件來創建主頁。
啟動 Laszlo 服務器
在可以使用 Run as Laszlo application 功能部署和測試 Laszlo 應用程序之前,您 的 OpenLaszlo 服務器必須在運行。
要在 Windows 中啟動 OpenLaszlo 服務器,請從 Windows 任務欄選擇 Start > Programs > OpenLaszlo Server > Start OpenLaszlo Server。
執行 Laszlo 資源管理器的 Apache Tomcat 的一個捆綁的實例試圖啟動。也可以通過 在運行 LPS 服務器時導航到 http://localhost:8080/lps-3.0.2/laszlo- explorer/index.jsp 而啟動資源管理器。
要關閉服務器,可從 Windows 任務欄選擇 Start > Programs > OpenLaszlo Server > Stop OpenLaszlo Server,或者在服務器控制台窗口為激活的情況下按 Ctrl + C。
布局應用程序主頁和導航
通過開發主頁(索引)和導航,開始 Laszlo 應用程序。導航是到視圖和創建工作的 兩個鏈接。導航使用了由 XML 數據集填充的 <tree> 組件。通過將代碼包含在 <library> 標記中,菜單代碼可作為包含文件可用。
清單 2 展示了 menu.lzx 文件的內容。
清單 2. menu.lzx 文件的內容
<library>
<!-- Menu data -->
<dataset name="fm">
<nav nav="View Work"
url="viewWork.lzx?lzt=html"/>
<nav nav="Create Work Order"
url="createWork.lzx?lzt=html"/>
</dataset>
<!-- START NAVIGATION -->
<view width="200" height="200" x="20" y="120">
<tree datapath="fm:/" autoscroll="true" showroot="false">
<tree datapath="*"
text="$path{'@nav'}"
open="true"
isleaf="true"
selectiontype="single">
<method event="onactivate">
var url = this.datapath.xpathQuery('@url');
if (url != null) {
LzBrowser.loadURL(url,'_self');
}
</method>
</tree>
</tree>
</view>
<!-- END NAVIGATION -->
</library>
圖 18 所示的索引頁面是一個簡單的頁面,只包含菜單和一個 logo。
圖 18. 索引頁面
索引的代碼執行一個菜單包含,也包含一個空的 <splash/> 標記,以便在加載 應用程序時向用戶展示一個進度條。<splash> 組件有兩種形式,用於控制加載應 用程序時的表示。一般的方式是,空標記或 <splash/> 默認觸發一個進度條。另 外,<splash/> 標記也可以包含視圖元素,用於用任何定制的圖像、元素或者您希 望的加載動畫覆蓋默認的進度條。
清單 3 展示了 index.lzx 文件的內容。
清單 3. index.lzx 文件的內容
<canvas>
<view resource="/images/fm.gif"/>
<menuseparator width="600" x="-1" y="97" height="6"/>
<include href="lz/tree.lzx"/>
<splash/>
<include href="menu.lzx"/>
</canvas>
布局 Work Order 表單
即使您不了解 Laszlo 組件,這項工作也並不太難,並且也不妨礙您創建復雜的用戶 界面。圖 19 所示的 Work Order 包含一個簡單的表單。
圖 19. FluidMotion work order 表單(Laszlo 表單元素)
Work Order 表單演示了使用一些不同的內置 Laszlo 組件。一個 XML 數據集驅動的 組合框用於樓宇和樓層選擇。包含樓宇和樓層數據的 XML 表示的位置數據集如清單 4 所 示。
清單 4. 位置數據集
<dataset name="location">
<locations>
<building id="1" name="HQ">
<floor id="1">Floor 1</floor>
<floor id="2">Floor 2</floor>
<floor id="3">Mezzanine</floor>
</building>
<building id="2" name="Trump Tower">
<floor id="1">Trump 1</floor>
<floor id="2">Trump 2</floor>
<floor id="3">Trump 150</floor>
</building>
</locations>
</dataset>
清單 5 包含用於樓宇和樓層組合框的代碼。
清單 5. 樓宇和樓層組合框
<text text="Building:"
fontstyle="bold" width="59" height="17"/>
<combobox defaulttext="choose one..." width="130"
editable="false" height="22" id="bl">
<textlistitem datapath="location:/locations[1]/building"
text="$path{'@name'}" id="bl_id"
value="$path{'@id'}"
onselect="getFloors(this.getValue());"/>
</combobox>
<text text="Floor:" fontstyle="bold" width="59"
height="17"/>
<combobox defaulttext="choose one..." width="130"
editable="false" height="22" id="fl">
<textlistitem id="fl_id" datapath=""
text="$path{'text()'}" value="$path{'@id'}"/>
</combobox>
注意 textlistitem 上的 datapath 屬性。它將下拉列表中的值綁定到前面描述的位 置數據集。冒號前面的文本表示數據集名稱。冒號後面的值是組件綁定到的 XPath。文本 和值分別使用 XPath 來選擇將用作下拉列表中項目的文本和值的數據集屬性。
在選擇了樓宇之後,事件通過調用 getFloors() 方法並將它傳遞給當前樓宇 ID,來 填充樓層組合框。清單 6 展示了樓宇組合框的 onselect 事件所調用的 getFloors() 方 法。
清單 6. getFloors() 方法
<script>
<![CDATA[
// Highlight urgent requests
function getFloors(bl) {
fl='location:/locations[1]/building[@id=\''+bl+'\']/floor';
this.fl_id.setAttribute('datapath', fl);
this.fl_id.setAttribute('value','');
}
]>
</script>
聯系人、e-mail、電話和描述(多行屬性設置為 true)是 <edittext> 組件。 例如:
<edittext id="contact" x="348" width="130" height="17"/>
下面的嚴重性 <slider> 組件允許請求者給工作單分配一個嚴重性:
<slider maxvalue="4" minvalue="1" text="Severity" id="severity"
keystep="1" bordersize="1" yoffset="17"/>
下面的 Submit 按鈕是一個標准的 <button> 組件,並允許提交表單。目前, 這個表單不會被提交。後面,該表單將被提交給 Web 服務。
<button isdefault="true" text="Submit" x="350" onclick=""/>
布局工作視圖
圖 20 所示的工作視圖使用 <grid> 組件以及其他嵌入式組件,來查看當前的 工作請求。
圖 20. FluidMotion view work 頁面(Laszlo 網格組件)
該網格是用清單 7 中的靜態數據集構建的,以建模它後面連接到的服務器端調用。
清單 7. 靜態數據集
<dataset name="work">
<work>
<wo id="100301">
<date_req>11/15/2005</date_req>
<date_last_mod>11/18/2005</date_last_mod>
<bl_name>HQ</bl_name>
<fl_name>Floor 3</fl_name>
<contact>Tim Dennison</contact>
<email>[email protected]</email>
<phone>679.111.1123</phone>
<description>
Need emergency service on my equipment!
</description>
<comments>I'm on it!</comments>
<severity>Low</severity>
<status>Complete</status>
</wo>
<wo id="100302">
<date_req>11/18/2005</date_req>
<date_last_mod>11/19/2005</date_last_mod>
<bl_name>Trump Tower</bl_name>
<fl_name>Trump 2</fl_name>
<contact>Donald Trump</contact>
<email>[email protected]</email>
<phone>603.239.4326</phone>
<description>
Need recruiter machine repaired.
</description>
<comments>This is on hold for now.</comments>
<severity>Urgent</severity>
<status>On Hold</status>
</wo>
</work>
</dataset>
這個 Laszlo <grid> 組件可以包含 <gridcolumn> 組件,如清單 8 所 示。
清單 8. Laszlo <grid> 組件可以包含 <gridcolumn> 組件
<grid datapath="work:/work[1]" contentdatapath="wo"
shownitems="7" height="135" width="625" id="wo_grid"
x="180" y="115" multiselect="false">
<gridcolumn resizable="false">Requested
<text datapath="date_req/text()" text="$path{'text()'}"/>
</gridcolumn>
<gridcolumn resizable="true" width="90">Contact
<text datapath="contact/text()"/>
</gridcolumn>
<gridcolumn resizable="false">Severity
<text datapath="severity/text()"/>
</gridcolumn>
<gridcolumn resizable="false" width="90">Status
<combobox defaulttext="Requested" editable="false"
id="status" datapath="status/text()">
<textlistitem text="Assigned" id="assigned"
value="assigned"/>
<textlistitem text="Active" id="active" value="active"/>
<textlistitem text="Complete" id="complete"
value="complete"/>
<textlistitem text="On Hold" id="hold" value="hold"/>
<textlistitem text="Cancelled" id="cancel"
value="cancel"/>
</combobox>
</gridcolumn>
<gridcolumn resizable="false" width="240">Comments
<inputtext datapath="comments/text()" id="comments"
text="comments/text()" multiline="true" height="35"
selectiontype="multi"/>
</gridcolumn>
</grid>
運行應用程序並調試
Laszlo IDE 允許開發人員從 IDE 啟動正在開發的當前文件。您可以利用如圖 21 所 示的 Run As 命令,方法是簡單地右擊文檔並選擇 Run As > Laszlo Application。 然後,IDE 就啟動了。
圖 21. Laszlo IDE 的 Run As 特性
可以通過利用 debug.write() 方法而構造調試語句。調試語句如下所示:
debug.write("getting floors for " + bl);
debug.write("setting floor datapath to " + fl);
要查看調試窗口和結果,請將 canvas 標記上的 debug 屬性設置為 true,如圖 22 所示。
<canvas width="100%" height="100%" debug="true">
圖 22. Laszlo Debugger 窗口
將 Laszlo 保存為 .war 文件(捆綁和部署)
Laszlo IDE 允許開發人員通過執行以下步驟而捆綁標准的 J2EE Web archive (WAR) 文件:
從 Eclipse 主菜單選擇 File > Export。
選擇 Laszlo WAR File,如圖 23 所示,並單擊 Next。
圖 23. Laszlo .war 文件 導出工具
如圖 24 所示,從 Project 組合框選擇一個 Laszlo 項目,並從 LPS 根目錄中的 OpenLaszlo 服務器的適當目錄,選擇一個具有 .war 擴展名的適當目的文件。
圖 24. Laszlo WAR Export 工具
Laszlo WAR Export 工具捆綁運行與 LPS 服務器無關的應用程序所需的所有必要的依 賴項。換句話說,它使得應用程序可以虛擬地部署和運行在任何 Java Web 容器上。依賴 項包括但不局限於所有的 .jar 文件、內置的 Laszlo 組件和 Laszlo DTD。它還包括所 有基本 Laszlo 組件、CSS 文件、Java 類文件、Flash 和 HTML。這一特性使得將富客戶 機應用程序打包、部署和集成到 J2EE 架構中非常容易。
將 Web 服務和客戶機綁定在一起
既然已經完成了 Web 服務,並布局了富客戶機,就必須將它們綁定在一起。本節中有 兩個例子,展示如何從 OpenLaszlo 客戶機調用 Web 服務。
簡單的 Web 服務調用
在前一個例子中,樓宇和樓層組合框的內容是從靜態位置數據集構建的。盡管這對於 布局應用程序來說沒有問題,但是它對於長期的維護來說不是一個好主意。您不想在每次 添加一個新的樓宇時都必須更新代碼。這可以形象化為一個從 Web 容器加載的 .xml 文 件,但是這也似乎有太多的工作需要維護。相反,該列表和其他選擇列表有可能來自 Web 服務和數據庫。因此,Web 服務具有一個 getBuildings() 操作。
清單 9 是一個調用 getBuildings() 操作的例子。
清單 9. getBuildings() 操作
<dataset name="location" />
<soap name="WorkOrderService"
wsdl="http://localhost:8080/fms/wsdl/WorkOrderService.wsdl"
autoload="true">
<remotecall name="getBuildings"
funcname="getBuildings" dataobject="location">
<method event="ondata" args="value">
debug.write(location.serialize());
</method>
</remotecall>
<method event="onload">
WorkOrderService.getBuildings.invoke();
</method>
<method event="onerror" args="error">
debug.write('error:', error);
</method>
</soap>
XML 已經從位置數據集刪除掉了。這現在動態地由來自 getBuildings() 操作調用的 XML 所填充。
接下來,使用 soap 元素定義 SOAP 服務器。這裡,您需要給它一個名稱和一個到利 用 Web 服務生成的 WSDL 的 URL。對於本例來說,自動加載 Web 服務,因為您想要用戶 一查看頁面就填充組合框。
在 SOAP 定義中,也需要在您將要使用 remotecall 元素調用的 Web 服務上聲明遠程 操作。這裡,您定義了 getBuildings 操作。name 屬性是在執行操作時 JavaScript 引 用的本地名稱,而 funcname 屬性必須匹配 WSDL 中的名稱,這與 Web 服務 Java 類一 樣。dataobject 屬性指出將用結果填充哪個數據集。指定前面使用過的位置數據集。
在 remotecall 中,您可以指定一個 ondata 事件。該事件在 Web 服務返回結果後將 被調用。在本例中,您只是將結果寫到調試器窗口。這也已經用於填充字段或其他東西。 即使寫到調試器的這一實現很簡單,它仍然很有價值,因為它是一個強大的工具。有時, Web 服務產生不像 XML 的 XML,最初用於設計用戶界面。也很難確定 OpenLaszlo 平台 如何解釋 XML。這個例子展示了,您如何可以在數據集上調用 serialize 方法,以將 XML 分成良好的 XML 格式。清單 10 是來自 Web 服務調用的例子,這不同於最初用於設 計的 XML。
清單 10. 在數據集上調用 serialize 方法以將 XML 分成良好的 XML 格式
<location>
<getBuildingsReturn>
<floors>
<floors>
<name>Floor 1</name>
<id>1</id>
</floors>
<floors>
<name>Floor 2</name>
<id>2</id>
</floors>
</floors>
<name>HQ</name>
<id>1</id>
</getBuildingsReturn>
<getBuildingsReturn>
<floors>
<floors>
<name>Trump 1</name>
<id>1</id>
</floors>
<floors>
<name>Trump 2</name>
<id>2</id>
</floors>
</floors>
<name>Trump Tower</name>
<id>2</id>
</getBuildingsReturn>
</location>
注意幾件事情。首先,Web 服務不使用任何屬性。每個數據項都是一個元素。其次, location,即數據集的名稱,是最外邊的 XML 元素。第三,buildings 被 getBuildingsReturn 所取代,後者是用附加到它的單詞 Return 所調用的方法的名稱。
還有兩個其余事件應用於 SOAP 定義而非遠程調用。它們是 onload 和 onerror。 onload 只是一個調用方法的方便方式,以便在最初查看頁面時填充復選框。當然,要讓 這件事在查看時立即發生,您還需要在 soap 元素上將 autoload 設置為 true。在 onload 中,在 WorkOrderService 上顯式地調用了 getBuildings() 操作。在 onerror 事件中,只將錯誤消息寫到調試器窗口,以便可以看到錯誤。
參數化 Web 服務調用
第二個 Web 服務提交一個新的工作單。這裡,調用 createWorkOrder 操作。清單 11 是包含在前一節的 WorkOrderService soap 定義中的定義。
清單 11. 包含在 WorkOrderService soap 定義中的定義
<remotecall name="createWorkOrder" funcname="createWorkOrder">
<param value="${contact.text}" />
<param value="${phone.text}" />
<param value="${email.text}" />
<param value="${description.text}" />
<param value="${bl.text}" />
<param value="${fl.text}" />
<param value="${severity.value}" />
<method event="ondata" args="value">
debug.write('New Work Order ID = ' + value);
</method>
</remotecall>
在本例中,您也在 Web 服務類中用等於 WSDL 和方法中的操作名的 name 和 funcname 聲明了一個遠程調用。因為該操作接受參數,所以您應該包含 param 元素。參 數的順序與 Web 服務類 createWorkOrder() 方法簽名相同。這裡,值引用 edittext 組 件和其他組件中的文本。這個 remotecall 也有一個 ondata 事件,用於將新工作單 ID 的返回值綁定到調試窗口。
警告:OpenLaszlo 要求 Web 服務至少返回一個值。它不能只是返回一個 void,或者 所調用的 onerror 事件。
要發起對 createWorkOrder 的調用,請添加一個 onclick 事件到按鈕,並在 createWorkOrder 遠程調用上調用 invoke 方法:
<button isdefault="true" text="Submit" x="350"
onclick="WorkOrderService.createWorkOrder.invoke()"/>
部署到 Apache Tomcat
在完成 Web 服務和 OpenLaszlo 客戶機之後,就應該部署應用程序了。
因為 Web 服務 (fms) 和 OpenLaszlo 客戶機 (fm) 的輸出都是 .war 文件,所以您 應該能夠將它們部署在任何兼容的 Web 容器或 J2EE 應用服務器上。因為部署是特定於 容器的,所以請參考您的容器文檔,了解部署應用程序的指令。Apache Tomcat 是一種流 行的 Web 容器,所以本節介紹如何將應用程序部署到這一類型的容器。
要在 Windows 中部署到 Apache Tomcat 服務器,請執行以下步驟:
將導出的 fm.war 和 fms.war 文件復制到 <jakarta-tomcat>/webapps 目錄。
通過執行 <jakarta-tomcat>/bin/startup.bat 腳本啟動 Apache Tomcat。
就是這些內容。要測試應用程序,請使用 Web 浏覽器導航到 http://localhost:8080/fm/index.lzx。
結束語
隨著富 Internet 應用程序的流行,OpenLaszlo 已經成為 Ajax 或 Macromedia Flex 強大的替代物。在本教程中,您看到了使用富組件庫和少量 XML 創建有吸引力和響應快 速的 OpenLaszlo 應用程序是多麼容易。還看到了通過將它與公開為 SOAP Web 服務的業 務層集成,OpenLaszlo 是多麼適合 J2EE 應用程序架構。最後,您學習了如何將它打包 和部署到 Apache Tomcat Web 容器。整個教程中,了解到了如何使用許多 Eclipse Laszlo IDE 和 Eclipse Web Tools 來簡化開發過程。