扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
延续服务器方式在许多方面都很出色 —— 有状态的编程模型和具有无状态性能的用户体验。这种方式的优点如下:
延续大大简化了 Web 开发模型。有了延续,就可以将 Web 应用程序看成具有一系列请求的应用程序,能够提供更多的用户信息。图 2 给出了修改后的应用程序流。在用户启动应用程序之后,Web 服务器处于控制之中。应用程序不再是应付以任意次序到达的任意请求,而是变成了与一个用户进行统一且直接的交谈。
图 2. 延续支持更自然的应用程序流
与许多高阶抽象相似,延续也有缺点。这些缺点将影响依赖于延续的整体方式。延续服务器必须解决下面这些常见问题:
延续是昂贵的。 将数据放进会话中更容易了,这意味着会有更多的人将更多的数据放进会话中。框架设计者可以利用一种称为部分延续(partial continuations)的方法来降低开销,按照这种方法,框架只保存延续中应用程序特有的部分。
URL 变得难看了。 大多数延续服务器会在 URL 后面附加一个难看的延续标识符。
用户范例改变了。 如果大量使用延续服务器,用户体验就会改变。Back 按钮实际上会工作,这种体验会让某些用户感到迷惑。例如,如果在购物车中放了某些东西之后点击 Back 按钮,您会期望应用程序将这些东西从购物车中去掉吗?
总的来说,我相信延续代表着一种重大的技术进步,在不久的将来您可能会看到流行的延续服务器实现。现在我们来看看其他语言中的某些实现,然后我展示一些具体的细节。
其他语言中的实现
有好几种语言都具有基于延续的方法。最常见的实现是用 Lisp、Ruby 和 Smalltalk 编写的。
还有一些没有在这里列出的延续服务器。目前,大多数延续服务器实现是用支持延续的语言编写的,而这些语言不是主流语言。但是,以后的情况可能会不一样。
Java 语言中的延续服务器
Java 开发人员正在注意到基于延续的方式对构建 Web 框架的好处,但是 Java 语言不支持本机延续。如果您的语言不支持延续,那么就只有几种办法了:模拟延续、将延续添加到现有的语言中或者选用另一种语言。不同的 Java 框架采用了不同的办法:
不一定非使用延续来捕获执行状态。暂停的线程和状态机都可以捕获执行状态。线程化方式简单地冻结并存储现有的线程。这种方式有一点儿受限制,因为它不提供无状态性能 —— 实际上是为每个用户使用一个单独的线程。
但是,状态机(state machine)是不错的延续方式。状态机是一种定义了状态之间的转换的程序。到目前为止,具有延续服务器特征的最流行的 Java 框架是 Spring 的 Web Flow。Web Flow 采用状态机形式对用户界面页面之间的导航进行建模。Web Flow 可以将程序流建模成 Java 对象,但是常常使用 XML 来描述程序流。请考虑清单 3 中来自 Web Flow 教程(参见 参考资料)的程序流表示:
清单 3. Web Flow 程序流表示
<?xml version="1.0" encoding="UTF-8"?> <webflow id="myFlow" start-state="displayForm"> <view-state id="displayForm" view="form"> <action-state id="processSubmit"> </webflow> |
这个流程有三个核心状态:displayForm、processSubmit 和 finish。这个程序流定义了使机器从一个状态转换到下一个状态的动作。例如,submit 将状态从 displayForm 转换到 processSubmit。Web Flow 在典型的模型-视图-控制器级别上操作。可以使用许多不同的视图技术来显示表单。
当从一个状态转换到下一个状态时,框架自动捕获当前状态,包括所有实例变量。这样就可以获得与其他延续服务器一样的 Back 按钮支持和有状态编程模型。这种方式不使用本机延续,但是具有延续服务器的许多优点,还有其他一些优点:
其他语言
Cocoon 使用 Rhino,这是一种插入到 JVM 中的 JavaScript 虚拟机。Cocoon 控制器使用一个修改过的 Rhino 版本来表达延续,所以 Cocoon 允许用 Java 或 JavaScript 来表达控制器逻辑。请考虑清单 4 中来自 Cocoon 教程的应用程序(参见 参考资料):
清单 4. 使用 Cocoon
try { if (operator == "plus") cocoon.sendPage("result.html", {result: a + b}); else if (operator == "minus") cocoon.sendPage("result.html", {result: a - b}); else if (operator == "multiply") cocoon.sendPage("result.html", {result: a * b}); else if (operator == "divide") cocoon.sendPage("result.html", {result: a / b}); else cocoon.sendPage("invalidOperator.html", {operator: operator}); } catch (e) { cocoon.sendPage("error.html", {message: "Operation failed: " + e.toString()}); } |
注意清单 4 中的 sendPage 方法。这个方法将一个页面发送给用户。这里没有支持 Back 按钮或者将用户数据保存到会话中所需的冗长代码 —— 这些都封装在 Cocoon 的框架中了。
实现延续
RIFE 框架实现它自己的延续,而 WebWork 框架使用 RIFE 的延续实现。Jetty 6 也包含一个用 Java 编写的延续实现。清单 5 给出了一个来自 RIFE 教程的例子,这个例子是一个猜数字游戏:
清单 5. RIFE 示例
while (mGuess != answer) { if (answer < mGuess) { |
在这个例子中,pause() 方法捕获延续并将模板发送回用户供操作。RIFE 使延续变得很简单,一般的 Web 开发人员也能够使用延续。
不远的将来
您可以看到,延续是 Web 开发框架中一项真正的技术进步。利用这种方式,可以获得更高的生产效率。另外,因为采用直观的 Java 代码(而不是数百个互不相连的 servlet)来表达 Web 应用程序,应用程序更容易理解和维护。
Web 开发方面新的发展使延续方式变得越来越重要。Ajax 应用程序可以异步地获得 Web 页面的一小部分并将结果编织进现有的页面中,而不是用传统的请求/响应模型来获得整个 Web 页面。但是 Ajax 应用程序可能会迫使应用程序长期维持与用户的连接,这样应用程序才能进行响应并使状态跟踪代码比较容易编写。这种做法破坏了无状态编程的优势,因为需要为每个连接的用户占用一定的资源。有了延续,就可以在延续中保存状态并根据需要恢复状态。
在不远的将来,硬件的改进会使延续所增加的资源消耗变得无足轻重。如果不经过彻底的革新,Web 开发框架仍然会太复杂。Ajax 会使 Web 开发更加复杂。这些因素都会促使人们接受延续服务器。在两年内,大多数新的 Web 开发将会使用某种延续服务器或延续的模拟。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者