http://www.ibm.com/developerworks/cn/web/wa-aj-simplejava3.html
简介:在本系列的第 1 部分,您了解了如何生成用来发送 Ajax 请求和处理 Ajax 响应的 JavaScript 代码。第 2 部分展示了如何使用约定和 JSP 标记文件创建 HTML 表单以最小化设置和配置。在本系列的第 3 部分中,您将了解如何开发基于 JavaScript 的客户端验证器和服务端验证器,后者被实现为支持 JavaScript 客户端验证器的 JSP 标记文件。此外,您还将了解如何使用资源包,它们会在更改后自动重载,而不需要重启应用程序。
客户端验证十分有用,因为它减少,甚至不需要将表单返回给用户以改正错误。但是,基于 JavaScript 的验证还不够,因为如果数据通过程序提交给服务器,或用户浏览器禁用了 JavaScript,这种验证都会被绕开。本文展示如何实现客户端和服务器端验证。
创建客户端验证器的层次结构
本节展示如何使用构造函数和 JavaScript 中的原型来构建对象层次结构,用于验证用户在 Web 浏览器中的输入。本节的所有代码都可以在示例应用程序的(参见下载部分)valid.js 文件中找到。
开发基础验证器
在 JavaScript 中,可以结合使用函数和new 操作符来创建对象。“构造函数” 必须使用this 来恰当地初始化对象属性。清单 1 给出了Validator() 函数,该函数有 4 个参数:表单名称、元素名称、ID 和消息。这些参数的值作为属性存储在当前对象中。
同一个构造函数创建的对象可以共享属性,这些属性存储在prototype 对象中。在清单 1 中,defaultMsgIndex 是所有实例共享的一个属性,这些实例由new Validator(...) 创建。当您试图访问属性或对象的方法时,JavaScript 引擎首先在对象的成员中查看。如果没有找到,引擎就会验证对象的原型(对象可能具有自己的原型)。因此,该原型链可用于实现继承(在后面讨论)。在本文的示例中,Validator 是对象层次结构的基础。
清单 1. Validator() 构造函数
function Validator(formName,elemName,outId,msg) {
if (formName)
this.formName = formName;
if (elemName)
this.elemName = elemName;
if (outId)
this.outId = outId;
if (msg)
this.msgList = ["",msg];
}
Validator.prototype.defaultMsgIndex = 0;
|
任何 JavaScript 函数都可以成为对象的方法。只需在对象构造函数中使用this.methodName = functionName 。由于方法通常可以被同一个构造函数创建的所有实例共享,所以可以将该方法与构造函数的原型进行关联。在这里可以通过使用constructorName.prototype.methodName 实现,如清单 2 所示:
清单 2. 验证器的 getFormValues() 方法
Validator.prototype.getFormValues = function() {
var elemValues = new Array();
var form = document.forms[this.formName];
var formElements = form.elements;
for (var i = 0; i < formElements.length; i++) {
var element = formElements[i];
if (element.name == this.elemName) {
var elemType = element.type.toLowerCase();
if (elemType == "text" || elemType == "textarea"
|| elemType == "password" || elemType == "hidden")
elemValues[elemValues.length] = element.value;
else if (elemType == "checkbox" && element.checked)
elemValues[elemValues.length]
= element.value ? element.value : "On";
else if (elemType == "radio" && element.checked)
elemValues[elemValues.length] = element.value;
else if (elemType.indexOf("select") != -1)
for (var j = 0; j < element.options.length; j++) {
var option = element.options[j];
if (option.selected) {
elemValues[elemValues.length]
= option.value ? option.value : option.text;
}
}
}
}
return elemValues;
}
|
清单 2 中的getFormValues() 方法返回表单元素(它的名称恰好与elemName 属性的值相同)的值。代表 Web 浏览器中的 HTML 表单的 DOM 对象通过document.forms[this.formName] 获得。然后,getFormValues() 遍历表单的elements ,根据 HTML 的类型处理每一个元素。
如果是文本、密码或隐藏字段,getFormValues() 方法只将元素的值添加给所返回的数组。如果元素的类型为复选框或单选框,只有选中 HTML 元素时,才会添加值。最后,如果元素是一个列表,选中项的值就会存储到返回的数组中。
层次结构中的每个验证器都需要一个方法来验证单个值。对于基础的Validator ,verify() 方法(如清单 3 所示)返回0 ,但其他验证器将用其自身方法代替这个方法。由verify() 返回的值用来在msgList 内查找消息。
清单 3. 验证器的 verify() 方法
Validator.prototype.verify = function(value) {
return 0;
}
|
showMsg() 方法(参见清单 4)通过innerHTML 属性向 HTML 元素插入一个消息。代表 HTML 元素的对象通过document.getElementById(this.outId) 获得。消息用htmlEncode() 函数进行编码,该函数在本系列的第 1 部分介绍过。这个辅助函数的代码可以在encode.js 中找到。
清单 4. 验证器的 showMsg() 方法
Validator.prototype.showMsg = function(index) {
document.getElementById(this.outId).innerHTML
= htmlEncode(this.msgList[index]);
}
|
清单 5 包含execute() 方法,它遍历由getFormValues() 返回的值,并为每个值调用verify() 。如果execute() 方法结束时msgIndex 为0 ,那么用户输入就是有效的。在本例中,showMsg() 通过将空白字符串存储到输出元素的innerHTML 属性,清除以前的所有消息。否则,调用showMsg() 之后会在 Web 页面上出现错误消息。
清单 5. 验证器的 execute() 方法
Validator.prototype.execute = function() {
var msgIndex = this.defaultMsgIndex;
var elemValues = this.getFormValues();
for (var i = 0; i < elemValues.length; i++)
if (elemValues[i]) {
msgIndex = this.verify(elemValues[i]);
if (msgIndex != 0)
break;
}
this.showMsg(msgIndex);
return msgIndex == 0;
}
|
实现具体的验证器
valid.js 文件包含一个针对所需字段的验证器。RequiredValidator() 构造函数(参见清单 6)的参数与Validator() 函数相同。为了用Validator() 初始化对象属性,RequiredValidator() 构造函数设置一个名为base() 的方法。在base() 的协助下调用Validator() 之后,RequiredValidator() 从当前对象删除base() 方法,因为不再需要它。
清单 6. RequiredValidator() 构造函数及其原型设置
function RequiredValidator(formName,msg) {
this.base = Validator;
this.base(formName,msg);
delete this.base;
}
RequiredValidator.prototype = new Validator();
RequiredValidator.prototype.defaultMsgIndex = 1;
RequiredValidator.prototype.verify = function(value) {
return value.length > 0 ? 0 : 1;
}
|
所有RequiredValidator 对象的原型都是一个Validator 实例,该实例没有任何属性,因为没有参数传递给Validator() 构造函数。通过设置这一原型,RequiredValidator “继承” 了为Validator 的原型定义的属性和方法。
例如,当调用RequiredValidator 对象的execute() 方法时,JavaScript 引擎首先在对象的方法中查找。由于对象没有execute() 方法,下一个将查找对象的原型,然后是原型的原型,依此类推。在本例中,RequiredValidator 的原型是Validator 实例,这个实例的原型具有execute() 方法。
RequiredValidator 原型的defaultMsgIndex 属性设置为1 ,因为如果元素值丢失,就应该报告错误。如果值不为空,verify() 方法返回0 ,如果需要的字段的值没有输入,就返回1 。
清单 7 给出了LengthValidator ,与RequiredValidator 十分类似。LengthValidator() 构造函数有 7 个参数:表单名称、必须验证其值的元素的名称、用来输出错误消息的元素的 ID、已验证的值的最小和最大的长度,以及两个错误消息。LengthValidator 的原型是一个新的Validator 实例,与RequiredValidator 中的情况类似。如果值有效,verify() 方法返回0 ,如果值太短,则返回1 ,如果太长,则返回2 。
清单 7. LengthValidator() 构造函数及其原型设置
function LengthValidator(formName,min,max,msgMin,msgMax) {
this.base = Validator;
this.base(formName,outId);
delete this.base;
this.min = min;
this.max = max;
this.msgList = ["",msgMax];
}
LengthValidator.prototype = new Validator();
LengthValidator.prototype.verify = function(value) {
if (value.length < this.min)
return 1;
if (value.length > this.max && this.max > 0)
return 2;
return 0;
}
|
为了轻松管理 Web 页面的验证器,valid.js 文件定义了ValidatorList() 构造函数(参见清单 8),它创建一个包含有验证器数组的对象。add() 方法可将一个验证器实例追加到该数组。execute() 方法遍历验证器列表,调用每个验证器的execute() 方法,这些验证器的属性与给定表单的名称和可选元素的名称相匹配。因此,ValidatorList 的execute() 方法可以验证整个表单,也可只验证表单中的某个元素。
清单 8. ValidatorList() 构造函数及其原型设置
function ValidatorList() {
this.validatorArray = new Array();
}
ValidatorList.prototype.add = function(validator) {
this.validatorArray[this.validatorArray.length] = validator;
}
ValidatorList.prototype.execute = function(formName,elemName) {
var valid = true;
for (var i = 0; i < this.validatorArray.length; i++) {
var validator = this.validatorArray[i];
if (validator.formName == formName)
if (!elemName || validator.elemName == elemName)
if (!validator.execute())
valid = false;
}
return valid;
}
var pageValidators = new ValidatorList();
|
构建一个服务器端验证器库
前一节展示了如何在客户端用 JavaScript 验证用户输入。一旦表单数据提交,出于安全或为了防止用户浏览器禁用了 JavaScript,最好在服务器端重新验证用户输入。本节将讨论作为验证器的一组 JSP 标记文件。
由于使用 JSP 句法并且可跨页重用,标记文件很容易在服务器上实现验证。此外,用来验证用户输入的标记文件能够生成在 Web 浏览器中进行验证的 JavaScript 代码。由于只需在 Web 页面中一次性指定验证器的属性,因此这项技术减少了编码工作。
使用 JSP 标记文件实现验证器
在 Web 页面中,上一节的 JavaScript 验证器需要<span> 元素和innerHTML 的帮助来显示这些元素的消息。这些元素由errMsg.tag 文件产生(如清单 9 所示):
清单 9. errMsg.tag 文件
<%@ attribute name="id" required="true" rtexprvalue="true" %>
<%@ tag body-content="scriptless" %>
<span id="${id}" class="ValidationError"><jsp:doBody/></span>
|
valid.css 文件(参见清单 10)定义了用于错误消息的ValidationError 样式类:
清单 10. valid.css 文件
.ValidationError { color: red; }
|
required.tag 文件(参见清单 11)为必需字段实现服务器端验证,并生成用来在客户端设置RequiredValidator 对象的 JavaScript 代码片段。这个标记文件定义两个属性:必需字段的名称和一个可选错误消息。
如果没有提供msg 属性,则required.tag 通过<dvu:useDefaultMsg/> 调用另一个标记文件来设定defaultValidMsg 映射,它包含了验证器的默认消息。然后,将required 消息存储到msg 变量。
接下来,required.tag 文件使用<dvu:errMsg> 生成<span> 元素,如果有错误消息,它就会包装这些消息。如果具有给定名称的请求参数缺失,即用户没有填写必需字段,那么此标记文件将用<c:out> 输出这个消息,并通过<dfu:addError> 标记向映射添加这个错误,这在本系列的第 2 部分介绍过。
随后,required.tag 文件生成一小段 JavaScript 代码,它将在 Web 浏览器中执行。此代码创建一个RequiredValidator 对象并将其添加到名为pageValidators 的 JavaScript 验证器列表中。本文前面的部分描述了RequiredValidator 。传递给RequiredValidator() 构造函数的字符串参数用<da:jstring> 标记编码,这在本系列的第 1 部分部分介绍过。
清单 11. required.tag 文件
<%@ attribute name="name" required="true" rtexprvalue="true" %>
<%@ attribute name="msg" required="false" rtexprvalue="true" %>
<%@ tag body-content="empty" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="da" tagdir="/WEB-INF/tags/dynamic/ajax" %>
<%@ taglib prefix="dfu" tagdir="/WEB-INF/tags/dynamic/forms/util" %>
<%@ taglib prefix="dvu" tagdir="/WEB-INF/tags/dynamic/valid/util" %>
<c:if test="${empty msg}">
<dvu:useDefaultMsg/>
<c:set var="msg" value="${defaultValidMsg.required}"/>
</c:if>
<c:set var="outId" value="${name}Required"/>
<dvu:errMsg id="${outId}">
<c:if test="${formPost && empty param[name]}">
<c:out value="${msg}"/>
<dfu:addError name="${name}" msg="${msg}"/>
</c:if>
</dvu:errMsg>
<script type="text/javascript">
pageValidators.add(new RequiredValidator(
<da:jstring value="${formName}"/>,<da:jstring value="${name}"/>,<da:jstring value="${outId}"/>,<da:jstring value="${msg}"/>));
</script>
|
length.tag 文件(如清单 12 所示)是另外一个验证器,可用来验证请求参数的长度。已验证的参数通常是表单元素的提交值。此标记文件接受 5 个属性:元素名称、最小和最大长度,以及两个可选错误消息。此标记文件会输出由<dvu:errMsg> 生成的<span> 元素中的所有错误消息,与required.tag 的情况十分相似。由length.tag 生成的 JavaScript 代码在客户端创建一个LengthValidator 对象。
清单 12. length.tag 文件
<%@ attribute name="name" required="true" rtexprvalue="true" %>
<%@ attribute name="min" required="false" rtexprvalue="true"
type="java.lang.Long" %>
<%@ attribute name="max" required="false" rtexprvalue="true"
type="java.lang.Long" %>
<%@ attribute name="msgMin" required="false" rtexprvalue="true" %>
<%@ attribute name="msgMax" required="false" rtexprvalue="true" %>
<%@ tag body-content="empty" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="da" tagdir="/WEB-INF/tags/dynamic/ajax" %>
<%@ taglib prefix="dfu" tagdir="/WEB-INF/tags/dynamic/forms/util" %>
<%@ taglib prefix="dvu" tagdir="/WEB-INF/tags/dynamic/valid/util" %>
<dvu:useDefaultMsg/>
<c:if test="${empty msgMin}">
<c:set var="msgMin" value="${defaultValidMsg.too_short}"/>
</c:if>
<c:if test="${empty msgMax}">
<c:set var="msgMax" value="${defaultValidMsg.too_long}"/>
</c:if>
<c:set var="outId" value="${name}Length"/>
<dvu:errMsg id="${outId}">
<c:if test="${formPost && !empty param[name]}">
<c:if test="${min != null && fn:length(param[name]) < min}">
<c:out value="${msgMin}"/>
<dfu:addError name="${name}" msg="${msgMin}"/>
</c:if>
<c:if test="${max != null && fn:length(param[name]) > max}">
<c:out value="${msgMax}"/>
<dfu:addError name="${name}" msg="${msgMax}"/>
</c:if>
</c:if>
</dvu:errMsg>
<script type="text/javascript">
pageValidators.add(new LengthValidator(<da:jstring value="${formName}"/>,${min != null ? min : 0},${max != null ? max : 0},<da:jstring value="${msgMin}"/>,<da:jstring value="${msgMax}"/>));
</script>
|
用 JSP 标记文件创建资源包
在 Java? 应用程序中,消息通常被存储在资源包中,这些资源包一般被编码为置于CLASSPATH 中的.properties 文件。当对资源包做了更改后,必须重启应用程序确保刷新.properties 文件。如果想避免重启应用程序,可以将消息和其他文本资源放到 JSP 标记文件中。当标记文件被更改后,应用服务器会自动重载标记文件。
清单 13 给出了useDefaultMsg.tag 文件,它定义了验证器的默认消息,并在java.util.HashMap 对象中将它们分组,这些对象在 JSPrequest 作用域中由<jsp:useBean> 创建。消息通过 JSTL 的<c:set> 标记放置到映射中。对于每个请求,useDefaultMsg.tag 文件会根据用户偏好的区域选择验证器将要使用的消息映射,用户区域通过${pageContext.request.locale} 获取。
清单 13. useDefaultMsg.tag 文件
<%@ tag body-content="scriptless" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:if test="${defaultValidMsg_en == null}">
<jsp:useBean id="defaultValidMsg_en" scope="request" class="java.util.HashMap">
<c:set target="${defaultValidMsg_en}" property="required" value="Required"/>
<c:set target="${defaultValidMsg_en}" property="too_short" value="Too short"/>
<c:set target="${defaultValidMsg_en}" property="too_long" value="Too long"/>
</jsp:useBean>
<c:if test="${!initParam.debug}">
<c:set var="defaultValidMsg_en" scope="application"
value="${requestScope.defaultValidMsg_en}"/>
</c:if>
</c:if>
...
<c:if test="${defaultValidMsg == null}">
<c:choose>
<c:when test="${fn:startsWith(pageContext.request.locale,'en')}">
<c:set var="defaultValidMsg" scope="request"
value="${defaultValidMsg_en}"/>
</c:when>
...
</c:choose>
</c:if>
|
此示例展示了如何实现可自动重载的资源。对于现实中的应用程序,可以增强这个机制,以便使用更简单的语法定义资源。例如,可以使用一个定制标记,而不是<c:set> ,避免必须为每个消息指定target 属性。此外,还也可以将不同区域的资源放置在不同的文件中,简化转换过程。
在开发过程中,应该在web.xml 文件中将debug 参数设为true (参见清单 14),以便为每个请求重新创建所有的消息映射,这让您可以进行更改而不需重启 Web 应用程序。但在生成环境中,就应将debug 切换为false ,在application 作用域中启用映射缓存。
清单 14. web.xml 文件
<web-app ...>
<context-param>
<param-name>skin</param-name>
<param-value>default</param-value>
</context-param>
<context-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</context-param>
</web-app>
|
为 Web 表单启用 JavaScript 验证器
至此,您已经知道如何在客户端及服务器端验证用户输入。接下来,将学习如何在 Web 浏览器中激活基于 JavaScript 的验证。表单元素的onblur 属性允许在元素丢失键盘焦点时执行某些 JavaScript 代码,这是验证用户刚输入的值的好时机。此外,<form> 标记的onsubmit 属性允许在单击 Submit 按钮后立即调用一个 JavaScript 函数,如果用户输入无效,甚至可以通过返回false 来取消表单的发布。
本系列的第 2 部分展示了如何用一组 JSP 标记文件生成 HTML 表单。您不必为增加验证支持而更改它们,因为表单标记文件使用attrList.tag 文件(如清单 15 所示)生成表单元素的动态属性。在第 2 部分中,您已经看到如何在attrList.tag 中添加默认样式。在这里我们修改这个文件,增加onblur 和onsubmit 属性,它们包含了用来执行 JavaScript 验证器的函数调用。
必须添加到 HTML 元素的class 、onblur 和onsubmit 属性放置在名为addMap 的java.util.HashMap 实例中。然后,attrList.tag 遍历map 和addMap 集的元素,生成元素的 HTML 属性。
清单 15. attrList.tag 文件
<%@ attribute name="tag" required="true" rtexprvalue="true" %>
<%@ attribute name="map" required="true" rtexprvalue="true"
type="java.util.Map" %>
<%@ tag body-content="empty" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<jsp:useBean id="addMap" class="java.util.HashMap"/>
<c:if test="${!empty initParam.skin}">
<c:set target="${addMap}" property="class"
value="${initParam.skin}_${tag}"/>
</c:if>
<c:if test="${tag=='input_text' || tag=='input_password' || tag=='input_radio'
|| tag=='textarea' || tag=='select'}">
<c:set target="${addMap}" property="onblur"
value="pageValidators.execute('${formName}',this.name)"/>
</c:if>
<c:if test="${tag=='form'}">
<c:set target="${addMap}" property="onsubmit"
value="return pageValidators.execute('${formName}')"/>
</c:if>
<c:forEach var="attr" items="${map}">
<c:if test="${addMap[attr.key] == null}">
${attr.key}="${fn:escapeXml(attr.value)}"
</c:if>
<c:if test="${addMap[attr.key] != null}">
<c:set var="sep" value="${fn:startsWith(attr.key,'on') ? ';' : ' '}"/>
<c:set target="${addMap}" property="${attr.key}"
value="${attr.value}${sep}${addMap[attr.key]}"/>
</c:if>
</c:forEach>
<c:forEach var="attr" items="${addMap}">
${attr.key}="${fn:escapeXml(attr.value)}"
</c:forEach>
|
向示例应用程序添加验证
本系列的第 2 部分给出了一个基于表单标记文件的简单 JSP 示例。本节将展示如何向 Web 表单添加验证。
更新 Web 表单
清单 16 包含SupportForm.jsp 页面的修改版本。注意,第一个变化是<%@page%> 指令,它有autoFlush="false" 和buffer="64kb" 属性。默认状态下,JSP 页面具有一个8kb 的缓冲区,满载动态生成的 HTML 后,它会自动刷新。缓冲区刷新后,页面将不能再使用<jsp:forward> 。
当用户输入无效时,form.tag 文件(用来实现SupportForm.jsp 页面中的<df:form> 标记)会使用<jsp:forward> 将 HTTP 请求分配给另一个页面SupportConfirm.jsp 。添加了验证代码后,由SupportForm.jsp 生成的 HTML 的将大于8kb 。因此,这个页面的缓冲区也相应增加,确保转发能正确进行。此外,也禁用了autoFlush ,目的是在缓冲区不足以容纳 Web 页面生成的整个 HTML 时,方便调试工作。
您还会发现SupportForm.jsp 页面的头也发生了变化,它声明验证器标记库(前缀是dv )、valid.css 文件和两个 JavaScript 文件(encode.js 和valid.js ),它们包含用于 HTML 编码和客户端验证的 JavaScript 函数。在整个SupportForm.jsp 页面,绝大多数表单元素的前面都带有<dv:required> ,而一些表单元素则使用<dv:length> 来验证所输入字符串的长度。
清单 16. SupportForm.jsp 示例
<%@ page autoFlush="false" buffer="64kb"%>
<%@ taglib prefix="df" tagdir="/WEB-INF/tags/dynamic/forms" %>
<%@ taglib prefix="dv" tagdir="/WEB-INF/tags/dynamic/valid" %>
<jsp:useBean id="supportBean" scope="request" class="formsdemo.SupportBean"/>
<html>
<head>
<title>Support Form</title>
<link rel="stylesheet" href="forms.css" type="text/css">
<link rel="stylesheet" href="valid.css" type="text/css">
<script src="encode.js" type="text/javascript">
</script>
<script src="valid.js" type="text/javascript">
</script>
</head>
<body>
<h1>Support Form</h1>
<df:form name="supportForm" model="${supportBean}"
action="SupportConfirm.jsp">
<p>Name:
<dv:required name="name"/>
<dv:length name="name" max="60"/> <br>
<df:input name="name" type="text" size="40"/>
<p>Email:
<dv:required name="email"/>
<dv:length name="email" max="60"/> <br>
<df:input name="email" type="text" size="40"/>
<p>Versions:
<dv:required name="versions"/> <br>
<df:select name="versions" multiple="true" size="5">
<df:option>2.0.1</df:option>
<df:option>2.0.0</df:option>
<df:option>1.1.0</df:option>
<df:option>1.0.1</df:option>
<df:option>1.0.0</df:option>
</df:select>
<p>Platform:
<dv:required name="platform"/> <br>
<df:input name="platform" type="radio" value="Windows"/> Windows <br>
<df:input name="platform" type="radio" value="Linux"/> Linux <br>
<df:input name="platform" type="radio" value="Mac"/> Mac <br>
<p>Browser:
<dv:required name="browser"/> <br>
<df:select name="browser" size="1">
<df:option value=""></df:option>
<df:option value="IE">IE</df:option>
<df:option value="Firefox">Firefox</df:option>
<df:option value="Netscape">Netscape</df:option>
<df:option value="Mozilla">Mozilla</df:option>
<df:option value="Opera">Opera</df:option>
<df:option value="Safari">Safari</df:option>
</df:select>
<p><df:input name="crash" type="checkbox"/> Causes browser crash
<p>Problem:
<dv:required name="problem"/>
<dv:length name="problem" min="100" max="2000"
msgMin="Cannot have less than 100 characters"
msgMax="Cannot have more than 2000 characters"/> <br>
<df:textarea name="problem" rows="10" cols="40"/>
<p><df:input name="submit" type="submit" value="Submit"/>
</df:form>
</body>
</html>
|
分析生成的 HTML
查看由SupportForm.jsp 页面生成的 HTML 时(清单 17 中显示了一部分),将会发现与客户端验证相关的属性和代码片段:
-
<form> 元素具有onsubmit 属性,该属性包含一个 JavaScript 调用,在整个表单有效时,此调用才返回true 。
- 当丢失键盘焦点时,
<input> 、<textarea> 和<select> 元素使用onblur 属性来验证它们的值。
- 每个验证器标记生成:
- 一个
<span> 元素,错误消息将被插入其中。
- 一段用来创建验证器对象的 JavaScript 代码。
清单 17. 由 SupportForm.jsp 生成的 HTML
<html>
<head>
<title>Support Form</title>
<link rel="stylesheet" href="forms.css" type="text/css">
<link rel="stylesheet" href="valid.css" type="text/css">
<script src="encode.js" type="text/javascript">
</script>
<script src="valid.js" type="text/javascript">
</script>
</head>
<body>
<h1>Support Form</h1>
<form name="supportForm" method="POST" class="default_form"
onsubmit="return pageValidators.execute('supportForm')">
...
<p>Email:
<span id="emailRequired" class="ValidationError">
</span>
<script type="text/javascript">
pageValidators.add(new RequiredValidator(
"supportForm","email","emailRequired","Required"));
</script>
<span id="emailLength" class="ValidationError">
</span>
<script type="text/javascript">
pageValidators.add(new LengthValidator(
"supportForm","emailLength",60,"Too short","Too long"));
</script>
<br>
<input name="email" type="text" size="40" class="default_input_text"
onblur="pageValidators.execute('supportForm',this.name)">
...
</form>
</body>
</html>
|
结束语
在本文,您学会了如何用 JavaScript 构造函数和原型构建一个客户端验证器的分层结构。此外,还学会了如何创建基于 JSP 标记文件的服务器端验证器和资源包。请继续关注本系列的下一篇文章,您将从中发现如何用 JSP 标记文件创建类似于 JSF 的组件。
代码下载地址:
http://download.csdn.net/detail/mr__fang/5091091 (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|