如果您的企业已经依赖于使用多层的企业 Java 应用,那么您也许比想象中更接近无线科技的未来。通过描述一个样本应用,Aashish Patil 向您展示了如何用最少的人力物力把您现有的企业 Java 基础构件连接到无线网络中去。
如果您的企业已经依赖于使用多层的企业 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 应用结构
在图 1 中,包含 JavaServer Page(JSP)和 Servlet 的那一层负责 什么是 WML?
正如 Web 浏览器显示 HTML 编码的数据一样,支持无线标记语言(WAP)的设备显示 WML 编码的数据;另外,正如 Web 开发人员使用 JavaScript 把脚本功能嵌入到 Web 页面一样,设备开发人员使用 WMLScript 把同样的功能嵌入到 WML 页面中。WML 是 XML 的一个子集,而对于精通 HTML 或其它标记语言的人来说它看起来很眼熟。WML 有一个独一无二的特征需要牢记:它像一盒卡片;一个单一的 HTML 文档显示成一个单一的 Web 文档,而一个单一的 WML 文档 可以包含很多卡片。WAP 设备的屏幕一次只能显示一张卡片。
生成动态 HTML 页面。而在 WAP 应用中,这一层将生成动态的无线标记语言(Wireless Markup Language,简称 WML)页面。因此,为了转换一个标准的 J2EE 应用使之为移动设备所使用,您将不得不编写新的 JSP,并且在某些情况下,还要编写新的 Servlet。企业 JavaBean(EJB)保持不变,因为它们与数据表现无关。
有些人认为 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 客户端到 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és 的搜索;在客户端使用传真机则更不切实际。取而代之的是 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。代码块上的注释指明了在哪里这些操作会被执行。
查看本文来源