WAP 构建 Java 应用-转

来源:互联网 发布:android socket编程 编辑:程序博客网 时间:2024/05/17 07:51

原文出处:http://www-900.ibm.com/developerWorks/cn/java/wi-entwap/index.shtml

充分利用现有的 EJB 使移动工作群体变得强大

Aashish Patil (ash01@vsnl.net)
理科硕士研究生,计算机科学系,Southern California 大学
2001 年 7 月

如果您的企业已经依赖于使用多层的企业 Java 应用,那么您也许比想象中更接近无线科技的未来。通过描述一个样本应用,Aashish Patil 向您展示了如何用最少的人力物力把您现有的企业 Java 基础构件连接到无线网络中去。使用现有的 EJB、修改过的 Servlet 以及新的 WML 和 WMLScript 页面会使这个过程产生一个飞跃。

无线应用协议(Wireless Application Protocol,WAP)可以提高一个企业现有 Web 体系结构的含金量。如果您已经使用了企业 Java 应用,您可以容易地将它们与 WAP 服务集成,这样可以为移动工作群体带来有用的数据和功能。在这篇文章里,我会涉及到使用与 WAP 相关的 J2EE 的基本要素,然后创建一个 WAP/企业 Java 样本应用,以展示您如何把自己的 EJB 连接到无线网络中去。

背景:J2EE 和 WAP
在阅读本文前,您应该对 Java 2 平台,Enterprise Edition(J2EE)体系结构有个基本的了解。您可以通过下面的
参考资料章节找到关于 J2EE 的更多信息的链接。作为一个回顾,下面是一张为台式客户机设计的典型 J2EE 应用的示意图。

图 1 — J2EE 应用结构
J2EE 应用结构

在图 1 中,包含 JavaServer Page(JSP)和 Servlet 的那一层负责生成动态 HTML 页面。而在 WAP 应用中,这一层将生成动态的无线标记语言(Wireless Markup Language,简称 WML)页面。因此,为了转换一个标准的 J2EE 应用使之为移动设备所使用,您将不得不编写新的 JSP,并且在某些情况下,还要编写新的 Servlet。企业 JavaBean(EJB)保持不变,因 为它们与数据表现无关。

什么是 WML?
正如 Web 浏览器显示 HTML 编码的数据一样,支持无线标记语言(WAP)的设备显示 WML 编码的数据;另外,正如 Web 开发人员使用 JavaScript 把脚本功能嵌入到 Web 页面一样,设备开发人员使用 WMLScript 把同样的功能嵌入到 WML 页面中。WML 是 XML 的一个子集,而对于精通 HTML 或其它标记语言的人来说它看起来很眼熟。WML 有一个独一无二的特征需要牢记:它像一盒卡片;一个单一的 HTML 文档显示成一个单一的 Web 文档,而一个单一的 WML 文档可以包含很多卡片。WAP 设备的屏幕一次只能显示一张卡片。关于一些 WML 和 WMLScript 的链接可以参阅下面的
参考资料章节。

有些人认为 Servlet 无需更改,或者说:只要把 Servlet 的输出简单地重定向到生成动态 WML 页面的 JSP 上就已经足够了。然而,Servlet 不能区别从台式机和从 WAP 设备发来的请求;既然 WAP 应用可能无法实现基于 Web 的体系结构的所有功能,所以在这方面并没有混淆的地方,这一点很重要。也正由于此,开发人员通常为 WAP 应用设计新的 Servlet。然而在大多数情况下,这些 Servlet 与那些在基于 Web 的体系结构上提供类似功能的 Servlet 非常相似。

在图 1 中没有出现但对 WAP 应用又很重要的另一个组件是 WAP 网关。这个组件负责 WAP 栈和 Internet 栈之间的相互转换。

图 2 是图 1 的改进版,显示了使用 WAP 设备作为客户端的 J2EE 应用的结构:

图 2 — WAP/J2EE 应用的结构
WAP/J2EE 应用的结构

按照图示,所有自 WAP 客户端到 Web 服务器的请求必须通过 WAP 网关发送。尽管 WAP 网关也可以作为放置 WML/WMLScript 页面的 WAP 服务器,但使用 Web 服务器来放置这些页面更为方便。

有很多 WAP 网关的部署方法。对于多数 WAP 应用来说,网关或由 ISP 部署,或由提供这个应用的公司来部署。后者更为安全,我们以后会解释;然而,如果用户要求在他们的 WAP 设备上进行多用途的网络访问,一个内部的 WAP 网关会很不方便。大多数非 ISP 不希望他们的网关被用来访问他们自己站点以外的其他站点;因此,为了访问其他站点,用户将不得不使用 ISP 网关。但对于被 WAP 客户端使用的每一个网关来说,用户都必须定义一个不同的连接,正如 Windows 98 的拨号网络一样 — 而且在每个设备上,这样连接的数目通常是有限的。这就增加了用户的不便性,并且在访问一个站点时造成 WAP 设备中的连接阻塞。

WAP 应用设计的考虑事项
当使用 WAP 时,一个习惯为台式客户机编写 J2EE 应用的开发人员会遇到一些新的挑战。以下是在构建 WAP 应用时您也许会碰到的一些问题。

我可以在屏幕上显示几行信息?
事实上,对显示多少行没有特别限制,只要不超过面板的最大尺寸就行(随设备的不同而不同)。然而,为了避免太多滚屏,每屏(即卡片)5 至 7 行最佳。

我应该考虑哪些安全问题?
一些电话不支持使用 POST 方法发送表单数据。因此,用户名和密码必须通过 GET 方法发送。在 WAP 网关上,如果日志功能被激活并且请求已被记录,管理员就有能看到用户名和密码。如果网关是由 ISP 或其它第三方提供的,这个问题就会特别突出。

即使一个安全的连接也不能完全消除安全隐患。那些发送到 WAP 网关的数据使用 WTLS(Wireless Transport Layer Security)加密,它使用与标准 TLS 相同的算法。然而,发送到 WAP 网关的数据是二进制的编码格式(对 WAP),所以这些加密后的数据必须用 TLS 解密和再加密以适用于因特网。经过一段时间以后,敏感数据在 WAP 网关上以明文的形式出现。黑客则会在适当的时刻,将内存中的信息转储出来,进而成功地访问这些敏感数据。

按照注释,解决该问题的一种办法是在自己公司(而不是在 ISP)设一个 WAP 网关。在这种情况下,一个可信的人可以操作网关,并且可以关闭日志功能。

您也可以用 WMLScript 来编写自定义的加密算法,以对客户端的用户名和密码进行加密。这只有在使用简单的算法时才有可能实现;在支持 DES 类的算法上,WMLScript 不够强大。

我怎样保持 Session?
WAP 客户端不支持 Cookie。这样,当用户在您的站点的不同页面之间穿梭时,为了在服务器端保留关于客户端的信息,在向服务器发送每个请求的同时,一个 Session ID 必须被当作参数传递。Session ID 的参数名根据 Servlet 引擎的不同而不同。

有时,缺省的 Session ID 长度很大幅度地增加了每个请求的长度。结果导致客户端或 WAP 网关可能将此请求看作一个无效的 URL 而拒绝。这样有必要缩短 Session ID 的长度。请查看一下您正在使用的 Servlet 引擎的说明文档中关于 Session ID 参数名的部分。如果您碰到过无效 URL 的错误,这个说明文档也应提供有关缩短 Session ID 值长度的指南。

构造样本应用
XYZ Ltd. 是一家生产 PDA,可佩戴的计算机,及其它普及计算设备的公司。公司的销售人员拜访客户,提供 XYZ 产品的现场演示;某些演示要求销售人员必须跑很远的路去客户那里。那么在路上,他们是怎么收到客户列表和其它重要数据的呢?

为此使用电子邮件会需要体积较大且昂贵的便携式电脑或无休止的 Internet caf閟 的搜索;在客户端使用传真机则更不切实际。取而代之的是 XYZ 的销售人员会通过支持 WAP 功能的设备接收数据,例如手机或 PDA。使用移动设备,销售人员能在拜访客户时向公司提供及时的反馈。公司就能马上安排给客户及时发货并维护目前的销售统计信息。

我们的应用有两个主要目标。首先,我们流动的销售人员应该能使用它在 WAP 设备上查看客户列表。第二,如果一个客户希望买货,那么销售人员应能使用设备来下订单。此外,任何 WAP 应用的一个重要目标应该是减少用户必要的按键数目。由于受手持设备的用户界面限制,用户需要输入的数据量应控制在最少。

这是一张显示我们系统的体系结构的流程示意图

图 3 — 应用流程示意图
应用流程示意图

用户首先必须登录以访问系统;然后他们能浏览客户列表和每个客户的详细信息。如果他们希望为某一特定的客户下订单,那么系统会提供他们一个产品列表,他们可以从中为该客户选择一个特定的产品。

在本文余下的大多数内容中,我们会讨论实现该应用的 Servlet 和 JSP 代码,并会考察 JSP 和 Servlet 一起工作的方式。关于每个 JavaServer Page 的讨论还配有图解,显示了 JSP 在设备屏幕上的输出。

清单 1,Login.jsp 接受用户名和密码,并把它们作为参数来调用 LoginServlet。对这个和其它所有的 JSP 来说,MIME 类型都应被设置成 text/vnd.wap.wml 类型。在传递请求的同时,上面的 Login.jsp 还传递了一个叫 SessionID 的参数。它必须与每个传送到服务器的请求一起传递。参数名 SessionID 是一个占位符;请参考应用服务器的说明文档,找到适用于您特定的应用服务器的正确的参数名。Java 方法 HttpServletResponse.encodeURL(String URL) 自动添加 Session ID;在我们的应用里,这已经被广泛地使用在 Servelet 中。


登录系统

验证空白的输入域时会出现问题。在 input 标记里有一个属性,它让您使输入域不为空:

<input name="name" type="text" emptyok="false"/>

一个手机用户必须访问各个独立的对话框屏幕去输入数据。问题出现了,因为用户宁愿选择直接访问下一盒或下一张卡片而不愿通过对话框屏幕去输入数据。一个用户面对如图 4 所示的屏幕时也许会遗漏密码并揿下 NEXT。

一个开发人员可以通过使用 WMLScript 的验证来避免这个问题的发生(通过使用 onclick 事件)。然而,直到输入一个值到输入框以后,您传递到 WMLScript 函数的代表输入域值的那个变量才开始被初始化。因此,若无密码键入,传递到该函数的是未初始化的变量和脚本错误结果。这个问题的解决方法是在服务器端验证所有的输入域。

清单 2,LoginServlet 是我们问题的解决方案:它可以认证销售人员,并把他记录在系统中。它也可以在服务器端为销售人员创建一个 Session。代码块上的注释指明了在哪里这些操作会被执行。一旦成功登录,设备显示如清单 3 所示的主菜单(MainMenu.jsp)。

如图 5 所示,该文件将两个链接显示在设备屏幕上。其中第二个终止了当前的 Session;第一个指向当前的客户列表。在当前版本的程序流程中,销售人员必须在开始任何销售交易之前先从列表中选择一个客户;有关销售产品的列表只能在后继的屏幕上显示(后面将会讨论到细节)。也有其它可能的程序流:举例来说,用来直接将用户送到产品列表的链接可以被加到主菜单中。但是,您不应该在任一菜单中提供太多链接,否则支持 WAP 的设备的小屏幕会因此而变得混乱不堪。


Login.jsp

在图 5 的主菜单中揿下 View Clients 将调用清单 4 中的 ClientViewServlet,它抽取销售人员将要拜访的客户列表。代码上的注释说明了 Servlet 怎样从客户端上找到该信息。接着 Servlet 将列表放到 Session 对象中并调用 ClientList.jsp。(这里和下一段中提到的 Session 对象是来自于 Java servlet 包中的 HttpSession 类。)

清单 5,ClientList.jsp 抽取由 ClientViewServlet 放置在 Session 中的客户列表;它显示了客户的姓名,但不是完整的详细信息(请参见图 6)。当选择一个用户时,销售人员则被定向到 ClientDetails.jsp


Login.jsp

注意:显示客户列表的任务由三个独立的部分完成 — ClientViewServletClientList.jspClientDetails.jsp。这样设计的原因是什么呢?

  1. 大多数 J2EE 架构的权威人士建议 JSP 不应该直接访问 EJB;而应使用诸如 Servlet 的中间件来进行与 EJB 的交互。ClientViewServlet 访问 EJB 并获得客户列表。
  2. 这个应用本可以如此设计,这样所有的用户信息都会包含在一个单一的 WML 文档中。在这个体系结构中,客户列表包含在 WML 盒中的一张卡片上,而单个客户的详细信息会包含在同一盒中的不同卡片上。不过该单一文档可能包含太多数据,以至于对一个低带宽的 WAP 设备来说不能立刻下载。如果客户数目过于庞大,所生成的数据总量很容易超过 WML 卡片盒所允许的最大容量。(最大容量随设备不同而有所区别;如 Nokia 7110 的最大编译卡片盒容量为 1.3 KB)。因此我们使用两个 JSP:ClientList.jsp — 显示客户列表,还有 ClientDetails.jsp — 显示单个客户的详细信息。

清单 6,ClientDetails.jsp 接受客户数组的索引号作为参数,其中索引号在 Session 中出现。接下来它抽取所选客户的详细信息并显示。如果销售人员希望为该客户下订单,他只要揿下 Items 按钮。这会调用清单 7,ItemListServlet,并且显示该订单的可选产品。


Login.jsp

清单 7,ItemListServlet 抽取销售人员可以销售的产品列表,并将列表置于 Session 中。然后它调用清单 8,ItemList.jsp

清单 8,ItemList.jsp 从 session 中抽取产品列表并显示产品名称。销售人员可选择一个产品去订货并揿下 Order 按钮去调用 PlaceOrder.jsp。数组中所选产品的索引被作为参数送到清单 9,PlaceOrder.jsp


Login.jsp

PlaceOrderServlet 从 Session 中获得销售人员、客户及产品的 ID。接着通过创建新的 Order Entity EJB 可以产生一个新的订单。成功的下单显示了订单的 ID 和下订单的时间。

在这一版本的应用中,销售人员在完成交易后的唯一选择便是返回主菜单(请参见图 9)。您也可修改代码以便使用户返回到客户或产品列表。


Login.jsp

如果注意观察,您会发觉销售人员只输入两次数据:登录时和为客户输入购买产品数量时。

关于代码
附带文件包含本文所有的 JSP 和 Servlet 代码,也包含必需的 EJB 代码。EJB 的 jar 文件和部署描述符也一起包含在内。所有屏幕截图均来自 Nokia WAP 模拟器 2.0 版。

结论
就像前面提到的那样,WAP 应用提供了非常好的增值服务。一个孤立的 WAP 应用是不可取的。然而,这样一个应用无需花费很多财力人力就可以方便地集成到一个现有的 Web 应用体系结构中去。您所需要的唯一新硬件是一台机器,以及用于 WAP 网关的软件;如果您使用的是自己 ISP 的网关,那么这项开销也可省去了。

现有的 HTML 页面需要被转换成 WML。然而,WML 不像 HTML 那么复杂,因为它不支持 HTML 的许多功能。因此,这并不是一件费时的工作。

WAP 也支持无线 BitMap(WBMP)格式的图片。然而,使用 WAP 设备的用户在连接时间上花费了不少钱,他们更感兴趣的是直接有效的信息而非奢华的界面。除非图片本身能传递信息,否则提供快速的信息比占用带宽和时间来传输图片会更好。

最后注意事项:尽管模拟器可以提供测试 WAP 应用的良好环境,但只有当它配合已部署好的 WAP 网关,运行在所有可能的目标 WAP 设备上时,WAP 应用才算作真正意义上的被完全测试过了。所有动态生成的页面在网关上被编译。因此,有必要知道您的网关支持哪些版本的 WAP。如果网关编译器只使用 WML 1.1,那么用 WML 1.2 编写的页面是毫无用处的。

参考资料



关于作者
Aashish Patil 不久前刚获得印度 Mumbai 的 Thadomal Shahani 工程技术学院的计算机工程系学士学位。在 Tata Consultancy Services,他作为实习生完成了一个关于支持 WAP 的股票交易的项目;本文是该项目的一个直接部分。今年秋季,他将赴 Southern California 大学攻读计算机科学系的硕士学位。可通过
ash01@vsnl.net 联系 Aashish。

原创粉丝点击