• 沒有找到結果。

这样一来,以 xwork 为核心,只需替换外围的协议转换组件,即可实现不同技术平台之间的 切换(如将面向 Servlet 的 Webwork 替换为面向 JMS 的协议转换器实现,即可在保留应用逻

在文檔中 Spring 开发指南 (頁 72-75)

此后,所有以.action 结尾的服务请求将由 ServletDispatcher 接管。

ServletDispatcher 接受到 Servlet Container 传递过来的请求,将进行一下几个动作:

1. 从请求的服务名(/login.action)中解析出对应的 Action 名称(login)

2. 遍历 HttpServletRequest、HttpSession、ServletContext 中的数据,并将其复制到 Webwork 的 Map 实现中,至此之后,所有数据操作均在此 Map 结构中进行,从 而将内部结构与 Servlet API 相分离。

至此,Webwork 的工作阶段结束,数据将传递给 XWork 进行下一步处理。从这里也可以看 到 Webwork 和 xwork 之间的切分点,Webwork 为 xwork 提供了一个面向 Servlet 的协议转换 器,将 Servlet 相关的数据转构转换成 xwork 所需要的通用数据格式,而 xwork 将完成实际的 服务调度和功能实现。

这样一来,以 xwork 为核心,只需替换外围的协议转换组件,即可实现不同技术平台之间的 切换(如将面向 Servlet 的 Webwork 替换为面向 JMS 的协议转换器实现,即可在保留应用逻 辑实现的情况下,实现不同外部技术平台之间的移植)。

3. 以上述信息作为参数,调用 ActionProxyFactory 创建对应的 ActionProxy 实例。

ActionProxyFactory 将 根据 Xwork 配置 文件( xwork.xml) 中的 设定 ,创 建 ActionProxy 实例,ActionProxy 中包含了 Action 的配置信息(包括 Action 名称,

对应实现类等等)。

4. ActionProxy 创建对应的 Action 实例,并根据配置进行一系列的处理程序。包括 执行相应的预处理程序(如通过 Interceptor 将 Map 中的请求数据转换为 Action 所需要的 Java 输入数据对象等),以及对 Action 运行结果进行后处理。

ActionInvocation 是 这 一 过 程 的 调 度 者 。 而 com.opensymphony.xwork.

DefaultActionInvocation 则是 XWork 中对 ActionInvocation 接口的标准实现,如 果有精力可以对此类进行仔细研读,掌握了这里面的玄机,相信 XWork 的引擎 就不再神秘。

下面我们来看配置文件:

xwork.xml:

<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN"

"http://www.opensymphony.com/xwork/xwork-1.0.dtd">

<xwork>

<include file="webwork-default.xml" />

<package name="default" extends="webwork-default">

<action name="login"

class="net.xiaxin.webwork.action.LoginAction">

<result name="success" type="dispatcher">

<param name="location">/main.jsp</param>

</result>

<result name="loginfail" type="dispatcher">

<param name="location">/index.jsp</param>

</result>

<interceptor-ref name="params" />

<interceptor-ref name="model-driven"/>

</action>

</package>

</xwork>

include

通过 include 节点,我们可以将其他配置文件导入到默认配置文件 xwork.xml 中。

从而实现良好的配置划分。

extends="webwork-default"

"webwork-default"是 webwork-default.xml

文件中定义的 package,这里通 过继承,"default" package 自动拥有"webwork-default" package 中的所有 定义关系。

这个特性为我们的配置带来了极大便利。在实际开发过程中,我们可以根据自身 的应用特点,定义相应的 package 模板,并在各个项目中加以重用,无需再在重复 繁琐的配置过程中消耗精力和时间。

此外,我们还可以在 Package 节点中指定 namespace,将我们的 action 分为若干个 逻辑区间。如:

<package name="default" namespace="/user"

extends="webwork-default">

就将此 package 中的 action 定义划归为/user 区间,之后在页面调用 action 的时候,

我们需要用/user/login.action 作为 form action 的属性值。其中的/user/就指定了此 action 的 namespace,通过这样的机制,我们可以将系统内的 action 进行逻辑分类,

从而使得各模块之间的划分更加清晰。

action

Action 配置节点,这里可以设定 Action 的名称和对应实现类。

result

通过 result 节点,可以定义 Action 返回语义,即根据返回值,决定处理模式以及 响应界面。

这里,返回值"success"(Action 调用返回值为 String 类型)对应的处理模式为

"dispatcher"。

可选的处理模式还有:

interceptor-ref

设定了施加于此 Action 的拦截器(interceptor)。关于拦截器,请参见稍后的“XWork 拦截器体系”部分。

interceptor-ref

定义的是一个拦截器的应用,具体的拦截器设定,实际上是继

承于

webwork-default package,我们可以在 webwork-default.xml

中找到

对应的"params"和"model-driven"拦截器设置:

<interceptors>

……

<interceptor name="params"

class="com.opensymphony.xwork.interceptor.ParametersInt erceptor" />

<interceptor name="model-driven"

class="com.opensymphony.xwork.interceptor.ModelDrivenIn terceptor" />

……

</interceptors>

"params"大概是 Webwork 中最重要、也最常用的一个 Interceptor。上面曾经将

MVC 工作流程划分为几个步骤,其中的第一步:

“将 Web 页面中的输入元素封装为一个(请求)数据对象”

就是通过"params"拦截器完成。Interceptor 将在 Action 之前被调用,因而,

Interceptor 也成为将 Webwork 传来的 MAP 格式的数据转换为强类型 Java 对象的 最佳实现场所。

"model-driven"则是针对 Action 的 Model 驱动模式的 interceptor 实现。具体描

述请参见稍后的“Action 驱动模式”部分

很可能我们的 Action 都需要对这两个 interceptor 进行引用。我们可以定义一个 interceptor-stack,将其作为一个 interceptor 组合在所有 Action 中引用。如,上面 的配置文件可修改为:

<xwork>

<include file="webwork-default.xml" />

<package name="default" extends="webwork-default">

<interceptors>

<interceptor-stack name="modelParamsStack">

<interceptor-ref name="params" />

<interceptor-ref name="model-driven" />

</interceptor-stack>

</interceptors>

<action name="login"

class="net.xiaxin.webwork.action.LoginAction">

<result name="success" type="dispatcher">

<param name="location">/main.jsp</param>

</result>

<result name="loginfail" type="dispatcher">

<param name="location">/index.jsp</param>

</result>

<interceptor-ref name="modelParamsStack" />

</action>

</package>

</xwork>

通过引入 interceptor-stack,我们可以减少 interceptor 的重复申明。

下面是我们的 Model 对象:

LoginInfo.java:

public class LoginInfo {

在文檔中 Spring 开发指南 (頁 72-75)