您的位置:首页 > 编程语言 > Java开发

struts表单验证详解

2008-12-25 18:12 656 查看
Struts的出现就是为了全面消除服务器断程序的脚本嵌套,全面分层,通常我们的表单在提交时都需要进行数据验证,而这在以前通常是用客户端的javascript进行过滤后再由服务器端的脚本进行验证,这样的缺点是移植性很差,每次都需要重新编写源程序,而struts框架则提供了一个很好的验证机制,它不需要再编写脚本,而是通过验证器进行验证.

struts验证又分为2种,一种是在ActionForm bean表单属性JavaBean的validate()方法中定义,在服务器断验证;另外一种则是通过验证器分别在客户端和服务器端进行双层验证.

1、在Struts的中央控制器中写了Struts的控制器角色,在这篇介绍下Struts的视图!
Struts的视图组件:
Struts框架中的视图组件主要包括:
JSP页面。
ActionForm类
Struts自定义标记。
消息资源。
其中,ActionForm类是Struts框架的核心组件之一,是Struts的关键视图组件。在这篇文章中,将讨论ActionForm类及其作用。
ActionForm的作用机理:
ActionForm本质上是一种JavaBean,是专门用来传递表单数据的DTD(Data Transfer Object,数据传递对象)。它包括用于表单数据验证的validate()方法和用于数据复位的reset()方法。
Struts框架利用ActionForm对象来临时存放视图页面中的表单数据。例如,一个登录页面会有一个用户名输入框和一个密码输入框,以及用来提交登录请求的按扭。当用户提交登录请求后,Struts将 用户名和密码两个输入域的数据自动填充到相应的ActionForm对象中,然后控制层可以从该ActionForm对象中读取用户输入的表单数据,也可以把来自模型层的数据存放到ActionForm中,然后返回给视图显示。
ActionForm有(request)和(session)两种作用域(scope)。如果ActionForm的作用域设定为request,ActionForm实例将保存在request对象中,像其他保存在request对象中的属性一样,仅在当前请求范围内有效。如果ActionForm的作用域设定为session,那么ActionForm实例将被保存在session对象中,同一个ActionForm实例在整个HTTP会话中有效。
在Struts框架 中,ActionForm的作用机理如下图:


当验证ActionForm时,如果检测到一个或多个验证错误,Struts框架会把错误转发回配置文件struts-config.xml中<action>元素的input属性所指定的输入页面。

ActionForm的使用方法:
下面通过在(Struts重构)构建一个简单的基于MVC模式的JavaWeb的例子,来介绍一下ActionForm的正确使用,包括如何创建,配置和访问。
1.创建ActionForm
可以扩展Struts软件包的ActionForm类来创建具体的ActionForm。Struts软件包中的ActionForm类本身 是一个抽象类,在扩展的时候,为每一个要从HTML表单中捕获的输入域定义一个属性,使表单输入域与ActionForm属性一一对应,以使ActionForm能够捕获需要的表单输入。定义了具体的属性,就可以覆盖父类 的validate()和reset()方法,来实现具体的ActionForm验证规则和初始化方法。
下面是我在(Struts重构)构建一个简单的基于MVC模式的JavaWeb里面的例子




/**//*


* Generated by MyEclipse Struts


* Template path: templates/java/JavaClass.vtl


*/


package struts.form;




import javax.servlet.http.HttpServletRequest;


import org.apache.struts.action.ActionErrors;


import org.apache.struts.action.ActionForm;


import org.apache.struts.action.ActionMapping;






/** *//**


* Struts框架的ActionForm对象,它可用来在用户和业务层之间舆用户的输入数据。


* ActionForm也叫FormBean.Struts框架会自动从请求中惧输入数据,再将 这些


* 数据交给一个使用FormBean的Action对象,接着FormBean可以再交给业务层


*/




public class LoginHandlerForm extends ActionForm

{




/**//*


* Generated fields


*/






/** *//** userName property */


private String userName;






/** *//** userPwd property */


private String userPwd;




//验证方法,主要用于验证视图上的数据,例如非空之类,


//如果要进行业务验证,则应该在Action中进行!


public ActionErrors validate(ActionMapping mapping,




HttpServletRequest request)

{




return null;


}


//初始化首先调用的方法




public void reset(ActionMapping mapping, HttpServletRequest request)

{


// TODO Auto-generated method stub


}






public String getUserName()

{


return userName;


}






public void setUserName(String userName)

{


this.userName = userName;


}








public String getUserPwd()

{


return userPwd;


}






public void setUserPwd(String userPwd)

{


this.userPwd = userPwd;


}


}
在以上的loginActionForm中,validate()方法和reset()方法是ActionForm中两种可以覆盖的方法。validate()方法中定义具体的ActionForm验证规则。

2.配置ActionForm
每创建一个ActionForm类,就需要在Struts的配置文件中配置这个类。如上的类配置如下:


<form-beans >


<form-bean name="loginHandlerForm" type="struts.form.LoginHandlerForm" />




</form-beans>
<form-beans>元素用来指定全体ActionForm的配置,一个Struts应用所有的ActionForm的配置都要位于该元素标记内。<form-beans>元素的子元素<form-bean>用来配置一个具体的ActionForm类,每个<form-bean>元素对应的内容为一个form bean实例。一旦定义了<form-bean>元素,就可以在Action中使用它了。

3.访问ActionForm
ActionForm可以被JSP,Struts自定义标记,Action或其他Web组件访问。访问ActionForm的一般方法如下:
a) 使用Struts HTML标记库
Struts HTML标记库提供了一组和ActionForm密码关联的标记,这些标记对应到HTML表单域。如<html:form>标记对应HTML的<form>标记,<html:text>对应HTML表单的text类型的<input>输入域。这些标记和ActionForm交互,以把ActionForm中的属性值显示出来。
b) 从request或session对象中取出ActionForm对象
根据作用域的不同,Struts框架把ActionForm实例保存在request或session对象中,保存时采用的key值为<form-bean>元素的名字,即name属性的值。因此,可以像取出任何存放在request或session对象中的属性一样取出ActionForm实例。如:


LoginHandlerForm loginHandlerForm = (LoginHandlerForm)request.getAttribute("loginHandlerForm");



c)在Action类的execute()方法中直接访问ActionForm
如果配置了ActionForm和Action映射,Struts框架就会把ActionForm作为参数传给Action类的execute()方法,在execute()方法中,可以直接读取或设置ActionForm属性。在Action中使用ActionForm的示例如下:


public ActionForward execute(ActionMapping mapping, ActionForm form,




HttpServletRequest request, HttpServletResponse response)

{


LoginHandlerForm loginHandlerForm = (LoginHandlerForm) form;


//从Form中取得表单数据


String userName = loginHandlerForm.getUserName();


String userPwd = loginHandlerForm.getUserPwd();


//

(略)


return mapping.findForward(forward);




}

表单的数据验证
在上面的LoginHandlerForm代码中我们看到validate()方法体几乎是空的,也就是说LoginHandlerForm没有启动对表单数据进行验证的功能。我们也看到validate()方法返回的是一个ActionErrors对象。该对象封装了验证过程中所发现的错误。
表单验证是ActionForm的一个主要的功能之一。要实现这个功能,我们需要采取4个步骤:
a)重写validate()方法。
b)在资源文件ApplicationResources.properties中设置可能的验证错误的标识。
c)要在配置文件struts-config.xml中,把<action>元素的validate属性设置为true(默认已经是true),并添加<message-resources>元素以指明资源文件的存放路径。
d)在相应输入页面的相应位置加入错误标记<html:errors>,以输出可能的验证错误。
如上代码,如果我们要在LoginHandlerForm中实现输入数据验证功能,则相应采取上术四步。
1.重写validate()方法,如下:


//验证方法,主要用于验证视图上的数据,例如非空之类,


//如果要进行业务验证,则应该在Action中进行!


public ActionErrors validate(ActionMapping mapping,




HttpServletRequest request)

{




ActionErrors errors = new ActionErrors();


if(userName == null || userName.length()<3)


//此处userName为错误key,在前面页面中要使用该名字以显示


errors.add("userName",new ActionMessage("error.login.userName",userName));


if(userPwd == null || userPwd.length()<3)


errors.add("userPwd",new ActionMessage("error.login.userPwd",userPwd));


return errors;


}
在以上代码中我们使用 了ActionErrors类和ActionMessage类。ActionErrors类封装了一组验证错误,它的用法类似 Map类。而ActionMessage类封装了单个验证错误,它的构造函数内的参数就指向资源文件内的一个错误文本。例如语句"ActionMessage("error.login.userName")"中的参数"error.login.userName" 其实就是资源文件ApplicationResources.properties中的一条错误文本的键(key)。通过ActionErrors对象的add()方法,可以把ActionMessage对象加入到ActionErrors对象中。
2.设置资源文件
在struts的资源文件ApplicationResources.properties中设置可能的验证错误的标识:


# Resources for parameter 'struts.ApplicationResources'


# Project MVCStruts


error.login.userName=用户名必须填写且长度不小于3


error.login.userName=密码必须填写且长度不小于3
在资源文件中我们不能直接写中文,否则会出现乱码,至于我这里中文一是方便看,二是我按照了插件,可以自动过滤!插件可参考解决Struts中ApplicationResources.properties文件不支持中文问题
3.修改配置文件struts-config.xml
将配置文件struts-config.xml中<action>元素的validate属性设置为true,此处,还需要<message-resources>元素,以指明资源文件的路径。如下:


<action


attribute="loginHandlerForm"


input="/login.jsp"


name="loginHandlerForm"


path="/loginHandler"


scope="request"


validate="true"


type="struts.action.LoginHandlerAction" >


<!-- action与视图组件的联系在配置文件中写,这样就大大降低了Action和VIEW的耦合性 -->


<forward name="success" path="/main.jsp" />


<forward name="fail" path="/register.jsp" />


</action>


<!-- 资源文件 -->


<message-resources parameter="struts.ApplicationResources" />



资源文件书写类似JAVA文件,有包之分,注意是点号,不要写成反斜杠/
4.在页面 中加入错误标记:




<%

@ page language="java" pageEncoding="GBK"%>




<%

@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>




<%

@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>


<html>


<head>


<title>JSP for LoginHandlerForm form</title>


</head>


<body>


<html:form action="/loginHandler">


userName : <html:text property="userName"/><html:errors property="userName"/><br/>


userPwd : <html:text property="userPwd"/><html:errors property="userPwd"/><br/>


<html:submit/><html:cancel/>


</html:form>


</body>


</html>





<html:errors>是struts的一个自定义标记。它能根据它的property属性从资源文件中取出相应的验证错误,并输入页面中指定的位置显示验证错误。
2、Struts1.2中创建验证框架的步骤:

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 >

注意:这些内容必须放在<message-resources>元素之后。该规则是由
" http://struts.apache.org/dtds/struts-config_1_2.dtd "文件制定的。

2、创建相关的组件:

为了实验的目的,我依次创建4个ActionForm类,一个JSP,一个Action类,以下是他们在struts-config.xml中的配置信息:

1 <form-beans >
2 <form-bean name="DVForm" type="org.apache.struts.validator.DynaValidatorForm">
3 <form-property name="name" type="java.lang.String" />
4 </form-bean>
5 <form-bean name="DVAForm" type="org.apache.struts.validator.DynaValidatorActionForm">
6 <form-property name="name" type="java.lang.String" />
7 </form-bean>
8 <form-bean name="VForm" type="com.kook.struts.form.HahaForm" />
9 <form-bean name="VAForm" type="com.kook.struts.form.HohoForm" />
10 </form-beans>
11
12 <global-exceptions />
13 <global-forwards />
14 <action-mappings >
15 < action
16 attribute="DVForm"
17 input="/form/index.jsp"
18 name="DVForm"
19 path="/index"
20 scope="request"
21 type="com.kook.struts.action.IndexAction" />
22 </action-mappings>

其中
<form-bean name="VForm" type="com.kook.struts.form.HahaForm" />是ValidatorForm类的子类
<form-bean name="VAForm" type="com.kook.struts.form.HohoForm" />是ValidatorActionForm类的子类

下面是JSP页面代码:

1 <html:form action="/index" onsubmit="return validateDVForm(this)">
2 name : <html:text property="name"/><html:errors property="name"/><br/>
3 <html:submit/>
4 </html:form>
5 <html:javascript formName="DVForm"/>

因为只是做表单验证,action类可以不用涉及,因此不列出action类的代码啦!

3、删除name="VForm" 和name="VAForm"的ActionForm中的validate方法。

因为这两个类不是动态的验证类,在使用向导生成代码的时候会自动覆盖父类的validate方法。如果不删除的话,根据类的多态性原理,会调用他们生成的validate方法,而不调用他们父类的该方法。但是,实际上,是他们父类的validate方法调用了validator框架的验证方法,因此我们没有必要再去重写他的这个方法。同时也要记得删除,因为向导生成的是空实现,不删除的话,起不到验证作用。切记切记!!!曾经在这吃啊担子滴!!

观察以上代码不难发现,表单中只有一个文本框,因此实验也是对这个文本框进行验证。

4、创建自定义的验证文件validation.xml,主要内容如下所示:

1 <form-validation>
2 <formset>
3 <form name="DVForm">
4 <field property="name" depends="required">
5
6 <arg0 name="required" key="lable.name"/>
7 </field>
8 </form>
9 </formset>
10 </form-validation>

其中key="lable.name "在资源文件中对应的内容为:lable.name=name,因此,当文本框中没有输入任何信息而提交的时候,将会反馈一条name is required.的信息。

下面开始实验,
实验的目的是:依次使用4种验证Form来实现表单的验证功能,
他们分别是:DynaValidatorForm,DynaValidatorActionForm,ValidatorForm,ValidatorActionForm。这也是前面为什么要创建4个ActionForm的目的,详细配置信息见前面struts-config.xml
而JSP页面只有一个,就是配置文件中的input="/form/index.jsp "

实验一:由DynaValidatorForm的子类DVForm来验证

validation.xml的内容为:

1 <form-validation>
2 <formset>
3 <form name="DVForm">
4 <field property="name" depends="required">
5
6 <arg0 name="required" key="lable.name"/>
7 </field>
8 </form>
9 </formset>
10 </form-validation>

struts-config.xml的内容为:

15 < action
16 attribute="DVForm"
17 input="/form/index.jsp"
18 name="DVForm"
19 path="/index"
20 scope="request"
21 type="com.kook.struts.action.IndexAction" />
22 </action-mappings>

/form/index.jsp的主要内容为:

1 <html:javascript formName="DVForm"/>
2 <html:form action="/index" onsubmit="return validateDVForm(this)">

< html:javascript formName = " DVForm " />的formName属性对应的是进行验证的ActionForm的name属性。onsubmit="return validateDVForm(this)"为固定写法,格式为:onsubmit="return validateXXX(this)",XXX为Form的name属性,其中首字母大写就可以了。

实验二: 由ValidatorForm的子类VForm来验证

他的配置信息只需要将实验一中底色为黄色高亮部分的DVForm换成VForm就可以了,他们的区别只在于一个是动态的,一个是非动态的。

实验三:由DynaValidatorActionForm的子类DVAForm来验证

该实验的配置信息只需要将实验一struts-config.xml中底色为黄色高亮部分的DVForm换成DVAForm就可以了,其次是修改validation.xml的内容,具体如下:

1 <form-validation>
2 <formset>
3 <form name="/index">
4 <field property="name" depends="required">
5 <arg0 name="required" key="lable.name"/>
6 </field>
7 </form>
8 </formset>
9 </form-validation>

区别是<form name="/index">中的name属性不再对应的是验证Form的name属性,而是其相对的action类的path属性

实验四:由ValidatorActionForm的子类VAForm来验证

与实验三一样,换掉struts-config.xml中底色为黄色高亮部分的DVAForm换成VAForm就可以了,validation.xml文件中的内容与实验三保持一致,<form name="/index">中的name属性不再对应的是验证Form的name属性,而是其相对的action类的path属性。

不过用DynaValidatorActionForm和ValidatorActionForm的时候好象不能使用客户端验证,只能使用服务器端验证。还得有高手指点,因此前台JSP页面得改成:

1 <html:form action="/index">
2 name : <html:text property="name"/><html:errors property="name"/><br/>
3 <html:submit/>
4 </html:form>

下面来介绍一下validation.xml文件中的一些元素信息:

1、<global>中定义的<constant>和<formset>中定义的<constant>
前者表示在全局范围内定义常量,可以在validation.xml文件中的其他<formset>中访问。访问格式为${constantName}
后者表示局部的常量定义,只能在声明他的<formset>中使用。

2、<field>元素中的几个子元素:
<!ELEMENT field (msg|arg|arg0|arg1|arg2|arg3|var)*>
也就是说他的所有子元素都可以是0-n个,这一点和孙卫琴的书有出入,以此为准。

msg元素
<msg name="" key="" bundle="" resource=""/>

name:表示验证规则的逻辑名;
key:对应资源文件中的key;
bundle:指定从哪个资源文件获取key值,缺省时为默认的资源文件;
resource:为true是表示从资源文件中获取key属性对应的信息,为false时表示直接显示key属性的内容,和资源文件无关。缺省为true。

Strust框架中指定了一些常用规则的对应文本,验证框架默认是从这些对应的文本中读取信息。但是我们可以通过指定msg元素来从自定义的资源文件或者是key中来获取消息。

arg.....元素用来指定复合文本中的参数,依次对应。他们的属性和msg的属性很相似,用法也是一样的。

var元素

1 <formset>
2 <form name="/index">
3 <field property="name" depends="required">
4 <arg0 name="required" key="${var:required}" resource="false"/>
5 <var>
6 <var-name>required</var-name>
7 <var-value>xx</var-value>
8 </var>
9 </field>
10 </form>
11 </formset>

如果执行了该验证的话,输出的结果为:xx is required.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: