JavaScud | Forum | JIRA | Blog |
  Dashboard > WebWork2文档中文化计划 > WebWork > Continuations
  WebWork2文档中文化计划 Log In View a printable version of the current page.  
  Continuations
Added by scud, last edited by scud on May 19, 2006  (view change)
Labels: 
(None)

Continuations是WebWork从RIFE项目借用的特性, 可以以极其简单的方式提供状态管理和类似向导的功能。(that allow for extremely simple state management and wizard-like functionality.)
Continuations现在还没有完成, 因此, 目前我们不推荐在重要的(heavy-use)产品开发中使用它. 我们将继续增强并稳定该特性,直到确信它能适用于极端的网站流量和用例.

设置

首先需要标识需要使用continuation支持的class所在的package(base package). 这需要在webwork.properties中使用属性 webwork.continuations.package 来标识. 通常, 可以设置顶级package名称(root package)如 com.acme. (这里的root package可以理解为package的前缀, 例如: 有两个package com.abc.p1和com.abc.p2, 那么只需要指定com.abc为webwork.continuations.package即可, 译注)

完成这一步骤后, WebWork会分析顶级package中的class并自动为使用continuation特性的class - 继承ActionSupport类并在 execute() 方法中调用 pause() 方法的class - 应用continuation支持.

URL Concerns (URL相关内容)

使用continuations特性必须由WebWork管理流程状态, 因此, 这要求应用程序必须将流程的ID告知WebWork. WebWork使用一个名为 continue 的参数为流程中的每一次请求提供一个唯一id来做到这一点. 如果使用URLForm标签来产生URL链接, 这些标签会自动完成这一工作(是指加入 continue 参数, 译注). 如果没有使用这些标签, continuations不会正确工作.

Interceptor Concerns (截取器相关内容)

由于continuations从根本上改变了Action执行的方式, 因此理解它会对截取器带来那些影响是十分重要的. 最重要的一点是continuations只有在execute()方法被调用时才会发生作用(原文为kick in, 译注). 这意味着每一次请求(不管是新请求还是持续的请求)都会调用截取器. 这就是尽管Java调用栈中的其他内容(这里指局部变量等运行时数据, 译注)看起来是一样的, 但却能够在Action中取得新的请求参数值(apply new request parameters to your action)的原因.

通常这正是你想要的功能, 除了某些截取器, 比如Execute and Wait Interceptor, 可能还有Token Session Interceptor, 他们对Action调用的流程/周期有着截然不同的预期(have very different expectations about the workflow/lifecycle of the action invocation, ExecuteAndWait和Token都会限制同一个Session的请求次数, 也就是说他们不"期望"看到相同的请求, 译注). 在这些情况下, 不能使用continuations.

Example(示例)

使用continuations非常容易. 最大的问题是截然不同的应用流程的会话风格. 通常情况下, 你会使用session级别的变量或隐藏表单字段来传递状态. 而在使用continuations时, 使用Java语言本身来控制状态. 下面是继承ActionSupport的Guess类的主体代码:

Content pulled from external source. Click here to refresh.
public class Guess extends ActionSupport implements Preparable {
    int guess;

    public void prepare() throws Exception {
        // We clear the error message state before the action.
        // That is because with continuations, the original (or cloned) action is being
        //  executed, which will still have the old errors and potentially cause problems,
        //  such as with the workflow interceptor
        clearErrorsAndMessages();
    }

    public String execute() throws Exception {
        int answer = new Random().nextInt(100) + 1;
        int tries = 5;

        while (answer != guess && tries > 0) {
            pause(Action.SUCCESS);

            if (guess > answer) {
                addFieldError("guess", "Too high!");
            } else if (guess < answer) {
                addFieldError("guess", "Too low!");
            }

            tries--;
        }

        if (answer == guess) {
            addActionMessage("You got it!");
        } else {
            addActionMessage("You ran out of tries, the answer was " + answer);
        }

        return Action.SUCCESS;
    }

    public void setGuess(int guess) {
        this.guess = guess;
    }
}

注意看class是如何将状态(本例中为tries)作为一个局部变量在execute()方法中保持的. WebWork的continuations特性能够在pause()方法执行后自动恢复(pick up)调用并将恢复(restore)全部局部变量, 就像循环"魔术般的"继续了一样(as if the logical loop is continuing "magically") (继续阅读以了解它是如何工作的).

Guess使用的视图没有什么特别的, 事实上他遵循 URL concerns 的要求使用Form标签来产生URL. 这将确保 continue 参数被包含在所有请求中.

Content pulled from external source. Click here to refresh.
<html>
<head>
    <title></title>
</head>

<body>
<#list actionMessages as msg>
    ${msg}
</#list>

<@ww.form action="guess" method="post">
    <@ww.textfield label="Guess" name="guess"/>
    <@ww.submit value="Guess"/>
</@ww.form>
</body>
</html>

Advanced: How it Works (进阶: 工作原理)

Continuations不是魔术, 虽然有时候看起来像是魔法. 事实上, 它使用某种非常智能的字节代码(byte-code)处理来完成工作. 这意味着 为了使用continuations, 你的应用部署环境必须允许使用定制的class loader来加载活动类 (基于安全设置, 译注). 这通常不是问题, 但在这里必须说明.

当class被请求加载时, WebWork会把请求转交给RIFE/Continuations模块, 该模块将检查几个条件:

  1. 该类继承了ActionSupport吗?
  2. 该类定义了execute()方法吗?
  3. 在execute()方法中, 调用了pause()方法吗?

如果三个条件的答案都是yes, 该类将被改动, execute()方法被使用try/catch, goto语句以及智能的"状态恢复"代码重写. 这些都是透明的不会影响调试或修改该类.

更多信息请参阅ActionSupport类pause()方法的JavaDocs文档:

立即中止action调用(通过抛出PauseException)并导致action调用返回指定的结果, 如#SUCCESS, #INPUT等.

当该action下一次被调用时(并且使用了相同的continue ID), 该方法将立即返回, 并将execute方法的整个调用栈恢复回来.

注意: 该方法 只能 在execute()方法中调用.

Site running on a free Atlassian Confluence Open Source Project License granted to WebWork China. Evaluate Confluence today.
Powered by Atlassian Confluence, the Enterprise Wiki. (Version: 2.5.3 Build:#808 May 29, 2007) - Bug/feature request - Contact Administrators