转载自:http://www.bianceng.cn/Programming/Java/201104/25443.htm
开始之前
本教程演示如何使用 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>tden@rockstar.rock</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>dtrump@trump.usa</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 来简化开发过程。