Let's go inside

this blog is deprecated as a result of laziness.
posts - 59, comments - 2, trackbacks - 0, articles - 0

Struts Validation框架浅尝

Posted on 2006-08-28 08:59 Earth 阅读(824) 评论(0)  编辑  收藏 所属分类: Java 、转载

配置 Struts Validation 框架

       相信正在阅读本文的读者都是对 struts 有一定经验的,对于 struts 到哪去下载、如何安装配置就不必笔者多言。此处仅仅只讨论 struts validation 框架的安装和配置。通常,我们有 2 种方法来进行这个过程。

-          方法一:

从 struts 自带的 webapps 目录下解压 struts-balnk.war 到项目的 web 工程目录。这是最简单创建 struts 工程的方式,在这个工程中就已经包含了一个 struts 应用的所有需要的开发包和这些包的基本配置,自然也包含了其中的 validation 框架。它非常适合在项目的初创阶段,我们所需做的就是在这个空白工程中填点什么就可以了。

-          方法二:

对于已经存在的 struts 工程,如何添加 valiadation 框架支持所需的步骤也非常简单。

1.       首先在 struts-config.xml 中添加以下内容

<plug-in className="org.apache.struts.validator.ValidatorPlugIn">

    <set-property property="pathnames"

        value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>

 </plug-in>

2.       然后在 web-inf 目录中创建 2 个文件 validator-rules.xml , validation.xml 。(这 2 个文件也可从 struts-balnk.war 中获取)。

3.       复制 validation 框架所需要的类包到 web-inf/lib 下,这些类包是: common-validator.jar 。

这样,我们就可以使用 struts 的 validation 框架了。

使用 validation 框架

      问题

       这是一个简单的用户管理程序,使用者可以对用户信息进行相应的 CRUD 操作(增查改删)。其中用户信息包含用户名称、用户地址、用户描述、用户密码。对于以上的各种操作,约束如下:

-          增加和修改:用户名称、用户地址、用户密码、用户密码确认为必填项,同时密码和确认密码 2 个域的值必须一致。

-          删除和查询:用户名称为必填项。

解决和使用步骤

1.       创建 struts 项目的基本环境。

2.       创建相应的页面,确定页面流程( page flow )。

3.       创建相应的 formbean :

²        strut1.1 版本解决办法:

为了简单起见使用 DynaActionForm 。又由于使用了 validation 框架,此处使用 DynaValidatorForm 。 struts-config.xm 的内容:

<form-bean name="editForm" type="org.apache.struts.validator.DynaValidatorForm">

<form-property name="id" type="java.lang.Integer"/>

<form-property name="name" type="java.lang.String"/>

     <form-property name="pwd1" type="java.lang.String"/>

     <form-property name="pwd2" type="java.lang.String"/>

<form-property name="address" type="java.lang.String"/>

<form-property name="desc" type="java.lang.String"/>

</form-bean>

然后,修改 web-inf 目录下的 validation.xml 文件内容,其中 form 的名字和各域的名字必须和 struts-config.xml 中一致:

<form name="/editForm ">

     <field property="name" depends="required">

          <arg0 key="editForm.name"/>

     </field>

     <field property="pwd1" depends="required,mask">

            <arg0 key="editForm.password"/>

          <var>

                <var-name>mask</var-name>

                <var-value>^[0-9a-zA-Z]*$</var-value>

          </var>

     </field>

     <field property="pwd2" depends="required,mask">

          <arg0 key="editForm.password"/>

          <var>

                <var-name>mask</var-name>

                <var-value>^[0-9a-zA-Z]*$</var-value>

          </var>

     </field>

<field property="address" depends="required ">

          <arg0 key="editForm.address"/>

     </field>

</form>

4.       创建相应的 Action ,同时 Action 的 validate 属性置为 true ,以启用 validation 框架。

5.       书写 ApplicationResources.properties ,添加错误信息。

²        struts1.1

errors.required={0} is required.

errors.minlength={0} can not be less than {1} characters.

errors.maxlength={0} can not be greater than {1} characters.

errors.invalid={0} is invalid.

 

errors.byte={0} must be a byte.

errors.short={0} must be a short.

errors.integer={0} must be an integer.

errors.long={0} must be a long.

errors.float={0} must be a float.

errors.double={0} must be a double.

 

errors.date={0} is not a date.

errors.range={0} is not in the range {1} through {2}.

errors.creditcard={0} is an invalid credit card number.

errors.email={0} is an invalid e-mail address.

 

editForm.name= name.

editForm.password= password.

editForm.address= address

6.       在相应的 jsp 中添加 <html:errors property="age"/>

从整个使用过程来看,就验证部分而言,使用 struts1.1 的开发效率大大的得到了提高,而且通过 validator-rules.xml 使验证方法能被不同的 formbean 复用,而且可维护性也大大的得到提高。通过 mask ,使得单个页面域的验证非常灵活。

但是细心的读者可能也发现了这个验证文件仅仅指明 2 个 password 域是必填的,但并没有满足他们必须是相等的这种情形的判断,对于这一点,我们可使用自定义的 validator 并将它添加到 validator-rules.xml 文件中来完成。

创建自定义的 validator

       对于 validator 的创建,可以归结为 3 步:

1.       创建 validator 类, validator 必须包含一个以 validate 开始的方法,并且它的函数签名必须如下:

validateXXX(java.lang.Object,

org.apache.commons.validator.ValidatorAction,

org.apache.commons.validator.Field,  org.apache.struts.action.ActionErrors,

javax.servlet.http.HttpServletRequest,  javax.servlet.ServletContext)

在本例中,自定义的 Validator 如下(摘至 Struts 提供的例子,用来提供 2 个域的相等性检查):

              public class CustomValidator {

public CustomValidator() {

super();

}

public static boolean validateTwoFields(  Object bean,

ValidatorAction va, Field field, ActionErrors errors, HttpServletRequest request) {

String value = ValidatorUtil.getValueAsString(bean, field.getProperty());

String sProperty2 = field.getVarValue("secondProperty");

String value2 = ValidatorUtil.getValueAsString(bean, sProperty2);

 

if (!GenericValidator.isBlankOrNull(value)) {

try {

if (!value.equals(value2)) {

errors.add( field.getKey(), Resources.getActionError(request, va, field));

return false;

}

} catch (Exception e) {

errors.add( field.getKey(), Resources.getActionError(request, va, field));

return false;

}

}

return true;

}

}

2.       添加到 validator-rules.xml 文件中:

<validator name="twofields" classname="examples.validator.CustomValidator"

     method="validateTwoFields" methodParams="java.lang.Object,

org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.Field,

org.apache.struts.action.ActionErrors, javax.servlet.http.HttpServletRequest"

msg="errors.twofields" />

                   在对应的属性文件中添加对应的消息( errors.twofiled )。

3.       在 validation.xml 中使用:

<field property="pwd1" depends="required,twofields">

         <arg0 key="editForm.password" />

           <arg1 name="twofields" key=" editForm.password2" />

           <var>

                    <var-name>secondProperty</var-name>

                    <var-value>pwd2</var-value>

           </var>

</field>

         通过自定义 validator , validation 框架的可扩展性大大的得到提高。而且也使得不同的验证方法能够很好的得到复用

javascript 支持

       在 web 应用中,使用 javascript 的机会非常多。虽然不少书上提及客户有可能从浏览器关闭 js 的执行,但是要想完全的不使用它,目前看来好像还不行。比如一些复杂的 UI 是必须通过 js 来实现的(如下拉式菜单等等)。那么 validation 框架支不支持客户端的 js 验证呢?

答案是:当然。具体做法是:

-          在页面 html:form 标签内部添加 onsubmit="return validateEditForm(this);" (具体的语法: validate+ 在 validation.xml 文件中定义的 form 的名字);如:

<html:form action="<%=action%>" method="post" onsubmit="return validateEditForm(this);">

-          在 html:form 内部块中添加: <html:javascript formName="editForm"/>

       如此 2 步即可。虽然, validation 框架非常简单易用,但是还是有需要注意的地方。

使用注意

1.       使用 validation 框架后, form 必须从 ValidatorForm 中派生,同时必须在你的 validate 方法中先调用基类的 validate 方法。对于使用 Dyna 开头的方法来创建 formbean 的读者,你也必须改为以 dyna 开头含有 validator 的 form 。

2.       注意 DynaValidatorForm ( ValidatorForm )和 DynaValidatorActionForm ( ValidatorActionForm )的区别。刚开始时从帮助中没看明白这 2 者的区别,后来从网上一篇文章中得到了用法的区别。前者主要的视角是 formbean ,而后者的视角是 action 。

当 formbean 被不同的 action 使用时,对于不同的 action 而言,使用的 formbean 的属性集合有大有小。此时如果仍然以 formbean 为主体,会造成其他 action 的不正常使用。因此, struts 中提出了 DynaValidatorActionForm ( ValidatorActionForm )。此时在 validation.xml 中的 form 标签的 name 属性改为 action 的 path 属性,又由于 action 中有 attribute 和 name 属性, validation 框架就可根据这个 action 得到对应的 formbean 。例子:

<formset>

  <form name="/createAddress">

    <field property="city"

          depends="required">

      <arg0 key="prompt.city"/>

    </field>

  </form>

  <form name="/editAddress">

    <field property="state"

          depends="required">

      <arg0 key="prompt.state"/>

    </field>

  </form>

</formset>

3.       与 DispatchAction 的配合。 Struts1.1 的 DispatchAction 使得相关的 Action 的关系紧密,大大减少了应用中 Action 的个数,但是随之而来也带来了使用 Validation 框架的不便,不能不说是一个遗憾。读者也许认为这种情况可以使用第 2 条的解决方案来解决,即采用 DyanValidatorActionForm ,然后在 Validation.xml 文件中 form 的名称使用不同的 Actiond 的 path ,即在 validation.xml 中使用: <form name="/user.do?method=doAdd"> 、     <form name="/user.do?method=doLoad"> 。然而,在目前的版本中 Validation 框架并不支持这种辨认。一种绕过这个情况的方法是,针对同一个 Action 实现类在 Struts-config.xml 文件中定义多个 Action 的 path ,在不需要进行验证的地方将 Action 的 validate 属性置为 false 。即:

struts-config.xml :

<action attribute="editForm" path="/user" name="editForm" input="/editUser.jsp"

parameter="method" scope="request" type="foxgem.struts.UserDispatchAction"

     validate="true">

               <forward name="load" path="/editUser.jsp"/>

               <forward name="action" path="/userquery.do?pageId=1"/>

</action>

       

<action attribute="editForm" path="/loaduser" name="editForm" input="/editUser.jsp"

          parameter="method" scope="request" type="foxgem.struts.UserDispatchAction"

          validate="false">

               <forward name="load" path="/editUser.jsp"/>

               <forward name="action" path="/userquery.do?pageId=1"/>

</action>

然后在 validation.xml 文件中使用 2 的方法。

结束语

       总的说来, validation 框架大大的提高了页面验证的开发效率,更吸引人的是这些验证方法可通过自定义的 validator 来得到复用。使得这些验证代码更加集中,可维护性得到加强。当然随着项目的进行, validation.xml 和 validator-rules.xml 会随之增长,这部分的维护工作加重了。

       同时,由于不能非常好的和 DispatchAction 一起协作,也使得大量使用 DispatchAction 的项目不能非常好的使用它。建议大量使用 DispatchAction 和页面验证非常复杂多变的项目可以暂时按原来的方法来验证,不使用 validation 框架。

       至于 validation 框架的其他详细信息,请参见 struts 的文档,在此不再赘述。

关于作者

胡键,西安交通大学工学硕士,热衷于 j2ee/.net 技术,是 OpenSource 的忠实拥护者。目前与友人创建西安烁程软件有限公司。公司主要致力于 java web 应用的开发,已有多个项目在能源、电力和交通行业得到应用。可以通过 james.hu@chinacodeline.com 与他取得联系。