JBoss Seam 页面流释疑(1)

转载自:alartin  - http://alarnan.spaces.live.com/blog/cns!819CBC613DE169EF!172.entry

 

Seam的页面流pageflow是很容易让人迷惑的。

这里首先要弄清楚术语,Web程序通常都是在不同页面间来回跳转来实现应用逻辑的,所以通常的说法是页面导航Page Navigation, 这是最普遍和广泛的说法。因此对于页面导航Page Navigation的约定,被称为页面导航规则Page Navigation Rule。这几个术语是独立于语言和具体Web框架的。

例如,在JSF开发中,我们使用outcome来实现页面导航。outcome本身就是一个字符串,我们通过某个方法返回的outcome字符串来判断下一步的逻辑步骤。当然这个工作需要通过页面和outcome字符串的匹配设置来完 成。例如在Seam的猜数字应用中,我们也可以使用JSF的outcome来实现页面导航:

<navigation-rule>
    <from-view-id>/numberGuess.jsp

</from-view-id>
        
    <navigation-case>
        <from-outcome>guess</from-outcome>
        <to-view-id>/numberGuess.jsp</to-view-id>
        <redirect/>
    </navigation-case>

    <navigation-case>
        <from-outcome>win

</from-outcome>
        <to-view-id>/win.jsp

</to-view-id>
        <redirect/>
    </navigation-case>
        
    <navigation-case>
        <from-outcome>lose</from-outcome>
        <to-view-id>/lose.jsp</to-view-id>
        <redirect/>
    </navigation-case>

</navigation-rule>

我们可以看到JSF页面导航配置的三要素:

  1. 从哪个地方来:from-view-id指明从numberGuess.jsp页面来
  2. 某个可能的产出(outcome)是什么:from-outcome指明这个产出是win
  3. 这个可能的产出对应到哪里去:to-view-id指明如果产出是win的话,那么导向win.jsp页面

但是你可能立刻就能发现这种处理方式的弊病来:

  1. 这种方式需要在代码中处理导航逻辑。尽管我们配置页面导航比较容易,但是实际上,我们增加了代码中的复杂性(有可能得不偿失啊)。
  2. 自由度太大。开发人员可以随意设置outcome的值和其导向页面这样当页面导航复杂度增加的时候管理起来非常困难。
  3. 约束性太小。这个缺点和第二个缺点有一定联系,约束性太小意味着,开发人员往往需要查看所有的页面文件*.jsp和整个配置文件navigation.xml才能明白全部的页面导航规则

这种方式的页面导航被称为无状态 的页面导航。

需要强调的是:对于这种无状态的页面导航方式,除了JSF导航(使用navigation.xml)外,Seam还支持一种自己实现的无状态页面导航(使用pages.xml或者某个页面的xxx.page.xml):

<page view-id="/admin/admin.xhtml ">
        <navigation >
            <rule if-outcome="ship">
                <redirect view-id="/admin/ship.xhtml"/>
            </rule>
            <rule if-outcome="accept">
                <redirect view-id="/admin/accept.xhtml"/>
            </rule>
        </navigation>
    </page>

这里Seam也使用了类似JSF的页面导航三要素:

  1. 从哪里来:page元素的view-id属性指明从/admin/admin.xhtml页面来
  2. 某个可能的产出(outcome): navigation元素中嵌套的rule元素的if-outcome属性指明可能的一个outcome是ship
  3. 到哪里去:rule元素中嵌套的redirect元素的view-id属性指明如果outcome属性是ship的话,导向ship.xhtml页面

如果,在你的Seam应用程序中你准备使用无状态的页面导航 的话,你有两种选择:

  1. 使用JSF导航:配置navigation.xml
  2. 使用Seam导航: 配置pages.xml或者某个xxx.page.xml

我们将在后面的文章中比较这两种选择。

Seam不仅仅只支持这种无状态的页面导航!更棒的是,Seam支持有状态的页面导航

提醒:在Seam中,Seam实现的页面导航被成为页面流Pageflow

  1. JSF页面导航被称为页面导航,而页面导航是广泛的术语
  2. Seam实现的页面导航被成为页面流Pageflow
  3. 页面流可以是无状态的页面导航,Seam自己实现的无状态的页面导航
  4. 页面流也可以是有状态的页面导航,Seam通过JBPM实现的有状态的页面导航

在我们讲解有状态的页面导航之前,我们先回顾一下无状态页面导航的弊病包括:虽然页面配置简单,但是代码中要控制页面导航规则;无法很容易的看清楚导航规则,因为约束小。

Seam通过使用JBPM来帮助我们支持创建有状态的页面导航

需要注意的是:Seam在两种层次上使用JBPM:

  1. 一种是在页面导航中使用JBPM;
  2. 另一种是在业务流程管理中使用JBPM.

这两者的层次是不一样的,这也是容易导致Seam初学者迷惑的地方,在这里我们先弄清楚这一点:JBPM是独立的流程管理引擎,在Seam中它被使用在两个不同的地方:页面导航和流程管理中。

实际上,Seam开发人员利用JBPM强大的定制功能,专门为页面导航定制了流程管理。Seam的使用者应该记住在Seam有状态的页面导航中page元素是JBPM节点Node的一种!这从侧面证明了JBPM强大的功能!

OK, 我们接着说JBPM在Seam中的使用。

首先看一下JBPM在页面导航中的作用:用来实现有状态的页面导航。

JBPM在这里用来定义单个对话中的页面流。一个Seam对话指的是单个 用户相对短时期内的交互

我们再来看一下JBPM在流程管理中的作用:用来进行流程管理。

业务流程可以跨越多个用户,多个对话 。其流程被持久化到JBPM数据库中,所以它是长时期 的。当然,管理多用户活动当然比管理单个用户活动复杂的多,包括复杂的任务管理和多路径并发管理。

你可能在你的应用程序中同时在这两个地方都使用JBPM!

OK,让我们回到有状态页面导航的主题上来。

还是使用猜数字应用。这回我们需要用xxx.jpdl.xml文件来配置有状态的页面导航(pageflow.jpdl.xml):

<pageflow-definition

 name="numberGuess">
    
   <start-page

 name="displayGuess" view-id="/numberGuess.jsp">
      <redirect/>
      <transition

 name="guess" to="evaluateGuess">
      	<action 

expression="#{numberGuess.guess}" />
      </transition>
   </start-page>
   
   <decision

 name="evaluateGuess" expression="#{numberGuess.correctGuess}">
      <transition

 name="true" to="win"/>
      <transition name="false" to="evaluateRemainingGuesses"/>
   </decision>
   
   <decision name="evaluateRemainingGuesses" expression="#{numberGuess.lastGuess}">
      <transition name="true" to="lose"/>
      <transition name="false" to="displayGuess"/>
   </decision>
   <process-state

 name="cheat">
      <sub-process

 name="cheat"/>
      <transition name="displayGuess"/>
   </process-state>
   <page

 name="win" view-id="/win.jsp">
      <redirect/>
      <end-conversation />
   </page>
   
   <page name="lose" view-id="/lose.jsp">
      <redirect/>
      <end-conversation />
   </page>
   
</pageflow-definition>
我们可以看到有状态的页面流是通过JBPM的JPDL(xxx.jpdl.xml)来配置的,几个要素:
  1. 页面流定义: pageflow-definition元素指明页面流名字
  2. 起始点:起始点包括两种可能的元素:start-page元素或者start-state元素(区别我们稍后介绍)指明页面流的起始点
  3. 页面:page元素指明页面流中的各个页面
  4. 转移:transition元素代替了无状态页面流的产出outcome作用,这里的转移将在具体页面中使用(例如在guessNumber.jspx文件中):<h:commandButton value="Guess" action="guess "/>,这个按钮激发的动作action名为guess, 而这个guess就是xxx.jpdl.xml文件中配置的一个转移(注意和无状态的页面流区别,这里的动作action指的是转移,而不是传统意义上的动作或方法调用)
  5. 动作:在转移元素中的action元素指明这个转移中发生的事件(和JBPM的转移的概念一致),还是上面的例子:<action expression="#{numberGuess.guess}" />,在xxx.jpdl.xml文件中转移guess中有个动作,这个动作是调用numberGuess对象的guess方法,并且这个转移 guess将导向evaluateGuess这个决策。所以逻辑是这样的: 用户 -> 点击Guess按钮 ->Guess按钮的action激发guess转移 ->guess转移激发numberGuess对象的guess方法 -> guess转移导向evaluateGuess决策
  6. 决策:decision元素
  7. 流程状态:process-state元素包含子流程元素sub-process


你可能感兴趣的:(jboss,jbpm,JSF,配置管理,seam)