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
是对象层次结构的基础。
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 所示:
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
内查找消息。
Validator.prototype.verify = function(value) { return 0; } |
showMsg()
方法(参见清单 4)通过innerHTML
属性向 HTML 元素插入一个消息。代表 HTML 元素的对象通过document.getElementById(this.outId)
获得。消息用htmlEncode()
函数进行编码,该函数在本系列的第 1 部分介绍过。这个辅助函数的代码可以在encode.js
中找到。
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 页面上出现错误消息。
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 页面中一次性指定验证器的属性,因此这项技术减少了编码工作。
在 Web 页面中,上一节的 JavaScript 验证器需要<span>
元素和innerHTML
的帮助来显示这些元素的消息。这些元素由errMsg.tag
文件产生(如清单 9 所示):
<%@ attribute name="id" required="true" rtexprvalue="true" %> <%@ tag body-content="scriptless" %> <span id="${id}" class="ValidationError"><jsp:doBody/></span> |
valid.css
文件(参见清单 10)定义了用于错误消息的ValidationError
样式类:
.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 部分部分介绍过。
<%@ 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
对象。
<%@ 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> |
在 Java™ 应用程序中,消息通常被存储在资源包中,这些资源包一般被编码为置于CLASSPATH
中的.properties
文件。当对资源包做了更改后,必须重启应用程序确保刷新.properties
文件。如果想避免重启应用程序,可以将消息和其他文本资源放到 JSP 标记文件中。当标记文件被更改后,应用服务器会自动重载标记文件。
清单 13 给出了useDefaultMsg.tag
文件,它定义了验证器的默认消息,并在java.util.HashMap
对象中将它们分组,这些对象在 JSPrequest
作用域中由<jsp:useBean>
创建。消息通过 JSTL 的<c:set>
标记放置到映射中。对于每个请求,useDefaultMsg.tag
文件会根据用户偏好的区域选择验证器将要使用的消息映射,用户区域通过${pageContext.request.locale}
获取。
<%@ 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
作用域中启用映射缓存。
<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 的验证。表单元素的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 属性。
<%@ 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 表单添加验证。
清单 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>
来验证所输入字符串的长度。
<%@ 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> |
查看由SupportForm.jsp
页面生成的 HTML 时(清单 17 中显示了一部分),将会发现与客户端验证相关的属性和代码片段:
-
<form>
元素具有onsubmit
属性,该属性包含一个 JavaScript 调用,在整个表单有效时,此调用才返回true
。 - 当丢失键盘焦点时,
<input>
、<textarea>
和<select>
元素使用onblur
属性来验证它们的值。 - 每个验证器标记生成:
清单 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 的组件。
代码下载地址:
原文链接:https://www.f2er.com/ajax/166726.html