首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

用 continuation 开发复杂的 Web 应用程序(7)用 Java 代码实现的 Continuation

用 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)的情况目前还不十分明朗。
返回列表