• 沒有找到結果。

如 Webwork、Apache Tapestry 等。Spring Framework 1.2 版本中也将引入。

在文檔中 Spring 开发指南 (頁 91-96)

Map.Entry entry = (Map.Entry) iterator.next();

stack.setValue(

entry.getKey().toString(), entry.getValue());

} }

} finally {

invocationContext.put(

InstantiatingNullHandler.CREATE_NULL_OBJECTS, Boolean.FALSE);

invocationContext.put(

XWorkMethodAccessor.DENY_METHOD_EXECUTION, Boolean.FALSE);

invocationContext.put(

XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.FALSE);

} } } }

ParametersInterceptor 扩 展 了 抽 象 类 AroundInterceptor 。 并 在 其 预 处 理 方 法

(before)中实现了数据的转换。

数据转换的过程并不复杂:

⑴ 首先由 ActionContext 获得 Map 型的参数集 parameters。

⑵ 由 ActionContext 获得值栈(OgnlValueStack)。

⑶ 遍历 parameters 中的各项数据。

⑷ 通过 OgnlValueStack,根据数据的键值,为 Model 对象填充属性数据。

OgnlValueStack 是 http://www.ognl.org6提供的一套可读写对象属性的类库(功能上有点类似 Jakarta Commons BeanUtils,以及 Spring BeanWrapper)。

OgnlValueStack 使用非常简单,下面这段示例代码将 User 对象的 name 属性设为“erica”。 OgnlValueStack stack = new OgnlValueStack();

stack.push(new User());//首先将欲赋值对象压入栈中

stack.setValue("name","erica");//为栈顶对象的指定属性名赋值

上面的代码中并没有发现将Model对象入栈的部分,是由于ActionInvocation在初始化的时候 已经预先完成了这个工作,如DefaultActionInvocation.init方法中代码所示:

6

OGNL=Object-Graph Navigation Language。提供基于表达式的对象属性访问功能。在许多项目中得到使用,

如 Webwork、Apache Tapestry 等。Spring Framework 1.2 版本中也将引入。

private void init() throws Exception {

Map contextMap = createContextMap();

createAction();

if (pushAction) {

stack.push(action);

}

……

}

输入校验

Web 应用开发中,我们常常面临如何保证输入数据合法性的头痛问题。实现输入数据 校验的方法无外乎两种:

1. 页面 Java Script 校验

2. 服务器端、执行逻辑代码之前进行数据校验

Struts、Spring MVC 均为服务器端的数据校验提供了良好支持。

对于客户端的校验,大多 MVC 框架力所不逮。

而 WebWork 则在提供灵活的服务器端数据校验机制的基础上,进一步提供了对页面 Java Script 数据校验的支持。这也可算是 WebWork 中的一个亮点。

与 Spring MVC 类似,XWork 也提供了一个 Validator 接口,所有数据校验类都必须实 现这个接口。

XWork 发 行 时 已 经 内 置 了 几 个 常 用 的 数 据 校 验 类 ( 位 于 包 com.opensymphony.xwork.validator.validators),同时也提供了 Validator 接口的几个抽象实现

(抽象类),以便于用户在此基础上进行扩展(如 FieldValidatorSupport)。

服务器端数据合法性校验的动作,发生在 Action 被调用之前。回忆之前关于 Xwork 拦 截器体系的讨论,我们自然想到,通过 Interceptor 在 Action 运作之前对其输入参数进行校 验是一个不错的思路。事实的确如此。WebWork 中提供了一个 ValidationInterceptor,它将 调用指定的 Validator 对输入的参数进行合法性校验。

对 这 一 细 节 感 兴 趣 的 读 者 可 参 考 Xwork 中 的 ActionValidatorManager 和 ValidationInterceptor 的实现代码。

下面我们将首先讨论 Validator 的使用,之后再完成一个针对特定需求的 Validator 实现。

为“用户登录”示例加入数据合法性校验:

1. 首先,为 Action 配置用于数据校验的 Interceptor:

<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" />

<interceptor-ref name="validationWorkflowStack" />

</action>

</package>

</xwork>

这 里 我 们 并 没 有 直 接 引 用 ValidationIncepteror 。 而 是 引 用 了 validationWorkflowStack,webwork-default.xml 中对其定义如下:

<interceptor-stack name="validationWorkflowStack">

<interceptor-ref name="defaultStack"/>

<interceptor-ref name="validation"/>

<interceptor-ref name="workflow"/>

</interceptor-stack>

这表明 validationWorkflowStack 实际上是三个 Interceptor 的顺序组合。

为什么要引用这样一个 Interceptor 组合,而不是直接引用 validation Inceptor?

这与我们的实际需求相关,在 Web 应用中,当输入数据非法时,一般的处理方式 是返回到输入界面,并提示数据非法。而这个 Interceptor 组合则通过三个 Interceptor 的协同实现了这一逻辑。由此也可见 Webwork 中拦截器体系设计的精妙所在。

2. 在 Class Path 的根目录(如 WEB-INF/classes)创建一个 validators.xml 文件,此 文件中包含当前应用中所有需要使用的 Validator。

Webwork 发行包中提供了一个 validators.xml 示例(\bin\validators.xml)可供参 考,一般而言,我们只需根据实际需要在此文件上进行修改即可。

对于我们的登录示例而言,需要校验的有两个字段,用户名和密码,校验逻辑 分别为:

1. 用户名不可为空

2. 密码不可为空,且长度必须为 4 到 6 位之间

这 里 , 我 们 通 过 Xwork 提 供 的 RequiredStringValidator 和 StringLengthFieldValidator 来实现这一校验逻辑。

<validators>

<validator name="required"

class="com.opensymphony.xwork.validator.validators.Requ iredStringValidator" />

<validator name="length"

class="com.opensymphony.xwork.validator.validators.Stri ngLengthFieldValidator" />

</validators>

配置非常简单,只需指定此 Validator 的实现类和及其名称。下面的数据校验 配置文件中,将通过此 Validator 名称,对实际的 Validator 实现类进行引用。

3. 针对页面表单字段配置对应的 Validator。

在我们的登录页面中,共有两个字段 model.username 和 model.password。为其 建立一个配置文件:LoginAction-validation.xml:

<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"

"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.d td">

<validators>

<field name="model.username">

<field-validator type="required">

<message>Please enter Username!</message>

</field-validator>

</field>

<field name="model.password">

<field-validator type="length">

<param name="minLength">4</param>

<param name="maxLength">6</param>

<message>

Password length must between ${minLength} and

${maxLength} chars!

</message>

</field-validator>

</field>

</validators>

配置文件有两种命名约定方式:

1. Action 类名-validation.xml

如上面的 LoginAction-validation.xml 2. Action 类名-Action 别名-validation.xml

如 LoginAction-login-validation.xml

其中 Action 别名就是 xwork.xml 中我们申明 Action 时为其设定的名称。

配置文件必须放置在与对应 Action 实现类相同的目录。

配置文件格式非常简单,结合 validators.xml,我们可以很直观的看出字段的

4. 修改 LoginAction,使继承 ActionSupport 类。

public class LoginAction extends ActionSupport implements

Action, ModelDriven

{

……

}

ActionSupport 类实现了数据校验错误信息、Action 运行错误信息的保存传递功 能。通过扩展 ActionSupport,LoginAction 即可携带执行过程中的状态信息,这 为之后的错误处理,以及面向用户的信息反馈提供了基础数据。

5. 修改页面,增加数据合法性校验错误提示:

<%@ page pageEncoding="gb2312"

contentType="text/html;charset=gb2312"%>

<%@ taglib prefix="ww" uri="webwork"%>

<html>

<style type="text/css">

.errorMessage {

color: red;

}

</style>

<body>

<form action="/login.action">

<ww:if test="hasFieldErrors()">

<span class="errorMessage">

<b>Errors:</b><br>

<ww:iterator value="fieldErrors">

<li><ww:property value="value[0]"/></li>

</ww:iterator>

</span>

</ww:if>

在文檔中 Spring 开发指南 (頁 91-96)