用 continuation 开发复杂的 Web 应用程序(7)用 Java 代码实现的 Continuation
- UID
- 1066743
|
用 continuation 开发复杂的 Web 应用程序(7)用 Java 代码实现的 Continuation
用 Java 代码实现的 ContinuationCocoon 更新的发行版提供了对 Flowscript 的纯 Java 解释器的支持。清单 7 显示了用于纯 Java 解释器的源代码:
清单 7. 用 Java 代码实现的应用流1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
| import org.apache.cocoon.components.flow.java.AbstractContinuable;
import org.apache.cocoon.components.flow.java.VarMap;
public class PosFlow extends AbstractContinuable
{
public void doSellItem()
{
double rate, amount, total, savings;
double discount, discrate;
int qty, delCost;
String zone, delOpt;
String url = "page/getRateAmt";
sendPageAndWait(url);
rate = Float.parseFloat(getRequest().getParameter("rate"));
qty = Integer.parseInt(getRequest().getParameter("qty"));
amount = rate*qty;
url="page/getZone";
sendPageAndWait(url, new VarMap().add("rate",rate).add("qty",qty));
zone = getRequest().getParameter("zone");
discount=0.02;
if (zone.equals("A"))
{
if (qty >= 100)
{
discount=0.1;
}
}
else if (zone.equals("B"))
{
if (qty >= 200)
{
discount=0.2;
}
}
discrate = 100*discount;
savings = discount*amount;
delCost=0;
delOpt = getRequest().getParameter("delOpt");
if (delOpt.equals("S"))
{
url="page/getShipOpt";
sendPageAndWait(url);
delCost = Integer.parseInt(getRequest().getParameter("delCost"));
}
total = amount + delCost - savings;
url="page/displayResult";
sendPageAndWait(url, new VarMap()
.add("discrate",discrate)
.add("total",total)
.add("savings",savings)
.add("delCost",delCost)
.add("amount", amount)
.add("discount", discount)
.add("zone", zone));
}
}
|
如清单 7 所示,Cocoon 提供了一个叫做 AbstractContinuable的抽象类,以及 sendPage和 sendPageAndWait函数的实现。 PosFlow类扩展了这个抽象类,并在叫做 doSellItem的方法中包含业务逻辑。这个方法的实现与清单 4 中 sellItem的 JavaScript 实现一样。
Java 实现的站点地图在清单 8 中,您可以看到基于 Java 的应用程序的站点地图。您可能注意到,它看起来与前一个站点地图非常相似。惟一的区别是流语言(flow language)是用 Java指定的,而脚本源代码则是用 PosFlow类指定的。
清单 8. 基于 Java 的实现的 Cocoon 站点地图1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| <?xml version="1.0"?>
<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
<map:flow language="java">
<map:script src="PosFlow"/>
</map:flow>
<map:pipelines>
<map:pipeline>
<map:match pattern="page/*">
<map:generate type="jx" src="screens/{1}.xml"/>
<map:transform src="context://samples/common/style/xsl/html/simple-page2html.xsl">
<map:parameter name="servletPath" value="{request:servletPath}"/>
<map:parameter name="sitemapURI" value="{request:sitemapURI}"/>
<map:parameter name="contextPath" value="{request:contextPath}"/>
<map:parameter name="file" value="/samples/flow/jxrate/screens/{1}.xml"/>
<map:parameter name="remove" value="{0}"/>
</map:transform>
<map:serialize/>
</map:match>
</map:pipeline>
<map:pipeline>
<map:match pattern="continue.*">
<map:call continuation="{1}"/>
</map:match>
<map:match pattern="">
<map:call function="sellItem"/>
</map:match>
</map:pipeline>
</map:pipelines>
</map:sitemap>
|
在 JavaScript 和 Java 实现之间的另一个小区别是:在与应用程序的 HTML 页面对应的 XML 模板中访问当前 continuation id的方式。通过研究清单 9 所示的基于 Java 实现的 getRateAmt页面的 XML 模板,您可以看到这个区别。可以用 JXPath 表达式 #{$continuation/id}访问 continuation id。
清单 9.getRateAmt 页面的 XML 文件1
2
3
4
5
6
7
8
9
10
11
| <?xml version="1.0"?>
<page>
<title>Get Rate and Quantity of item to be purchased</title>
<content>
<form method="post" action="continue.#{$continuation/id}">
<para>Enter Rate: <input type="text" name="rate"/></para>
<para>Enter Quantity: <input type="text" name="qty"/></para>
<input type="submit" name="submit" value="Next"/>
</form>
</content>
</page>
|
continuation 的优缺点正如我在前面几节介绍的,continuation 实际上提供了把会话状态添加到 Web 应用程序的一种方法。使用 continuation 的优势是:可以很容易地处理异常的导航模式;可以很容易地用调试工具在应用程序中运行到某一点上,不必在分散的代码库的多个位置设置断点;理解和沟通程序的结构变得非常容易,理解和沟通整个应用程序中可能的 Web 导航路径也变得非常容易。
用 continuation 进行 Web 开发最大的问题是,目前常用的开发 Web 应用程序的语言、框架和环境,支持 continuation 的不多。continuation 和 CPS 自身的概念看起来很神秘、不直观。第二个大问题是,应当在哪以及如何存储 continuation。我们可以把它们存储在客户端,但是由于前面提到过的问题(cookie 会在克隆的浏览器窗口的所有实例之间共享),所以可行的选择是把整个 continuation 以序列化的形式保存在隐藏的表单字段中。我们也可以把它们保存在服务器端,我在示例程序中就是这么做的,但是如果这么做,就不得不注意像垃圾搜集、集群结点间复制这样的问题。最后,基于 continuation 的 Web 应用程序的效率(performance-wise)的情况目前还不十分明朗。 |
|
|
|
|
|