使用JSP标签库验证用户的输入(2)
验证JSP视图
通常要添加验证,程序员需要一个独立的JSP页面,它看起来象原来的表单页面,但是有错误信息,而且当表单域有问题时能被服务器(重定向)显示出来。我简单的在原JSP页面中加入了错误逻辑。当表单第一次被显示时,错误检查不会执行。在提交行为上,表单被提交给自己,域被JSP标签所验证(在服务器端,JSP被编译为Servlets)。如果所有的都正确,数据被提交到主控制器Servlet。如果不是都正确,用户将会在同一个JSP页面中看到一个错误消息。
在JSP页面中,我用Java脚本创建了一个boolean标志变量 "validate"。如果有一个 "validate" 参数被提交到JSP就设置它为 true 。
<% boolean validate = ("true".equals((String)request.getParameter("validate"))); %>
基于这个Boolean变量的值,JSP将使用我的标签进行验证。当页面第一次被装载,这个变量是false 的,验证不会执行。
要提交页面到它自己然后重定向到主控制器Servlet,我改变了表单行为来指向 <%=request.getRequestURI()%> 并添加了默认的转发标签<jsp:forward page="../MainServlet" />。
当用户提交这个表单时,它提交所有的值到同一个JSP,然后设置 validate 变量为true,并使用标签进行检查工作。如果数据审核通过,JSP转发所有的值到控制器Servlet。
如果途中遇到问题,标签体将会执行,并告诉JSP重新提交值给它自己,伴随的是根据错误而显示错误信息。请注意,标签体中的另一个Boolean变量“success”。这个变量初始设置为true,仅仅是用来检查是否有标签体被执行。只有当表单转发的 "validate" 和"success" 变量都true时,这个才能确定。具体请看Listing 2。
在有多个域需要验证的情况下,来自标签体的错误消息将显示这个不正确的域,从而减少了每次用户纠正错误和重新提交的时间。(这里的域就是表单中的域,如文本域等)
错误的邮政编码结果:
正确的邮政编码结果:
结论
我放入JSP中的额外逻辑,在同一页面中使用标签来执行验证,从而使得我创建了一个简单的高度可重用的服务器端数据验证解决方案,而不需要多个JSP或者Servlet来执行验证。一个标签是需要验证各种类型的域的;例如,e-mail,电话,或者只允许整数值的域。这种设计扩展了MVC项目中的JSP视图层。通过使用标签,也可以增加表示层和逻辑层的分离。在标签代码被修改的情况下,使用JSP标签来验证数据的Web设计者和开发者们不用改变任何JSP代码;而且,他们甚至不用知道验证的细节和任何使用到的JAVA语法。他们要做的事情就是简单的包含一个类似HTML的标签到他们的JSP页面中。
Code Listings
Listing 1
public int doStartTag() throws JspException {
// retrun code of 1 will cause tag body to execute
if (value == null)
return this.EVAL_BODY_INCLUDE; //check if we have zip code
if (value.equals(null))
//check if value is not null
return this.EVAL_BODY_INCLUDE;
if (value.length() == 5) {
//has to be an integer! short case of zip code xxxxx
try {
Integer.parseInt(value);
return this.SKIP_BODY;
} catch (NumberFormatException e) {
return this.EVAL_BODY_INCLUDE;
}
} else if (value.length() == 10) {
// long case of Zip code xxxxx-xxxx
String part1 = value.substring(0, 5);
String dash = value.substring(5, 6);
String part2 = value.substring(6);
if (!dash.equals("-"))
return this.EVAL_BODY_INCLUDE;
try {
Integer.parseInt(part1);
Integer.parseInt(part2);
return this.SKIP_BODY;
} catch (NumberFormatException e) {
return this.EVAL_BODY_INCLUDE;
}
}
return this.EVAL_BODY_INCLUDE; // all other cases
Listing 2<FORM action="<%=request.getRequestURI()%>" method="post">
<TABLE border="1">
<input type="hidden" name="ACTIONKEY" value="WeatherAction.viewByZip">
<input type="hidden" name="REDIRECTKEY" value="weather_data">
<input type="hidden" name="validate" value="true">
<TBODY>
<TR>
<TD><font face=Arial size=2>Zip:</font></TD>
<TD>
<% if (validate) { %>
<valTag:notValidZip value="<%=request.getParameter(\"ZIP\")%>">
<!-- do something if field is empty -->
<font color=red face=arial size=2>
Please enter valid Zip Code
</font><
br>
<% success=false; %>
</valTag:notValidZip>
<% } %>
<INPUT type="text" name="ZIP" value="<%=((validate)?request.getParameter("ZIP"):"")%>">
<% if (success && validate) { %>
<jsp:forward page="../MainServlet" />
<% } %>
</TD>
</TR>
<TR>
<TD></TD>
<TD><INPUT type="submit" name="view" value="View"></TD>
</TR>
</TBODY>
</TABLE>
</FORM>
Listing 3
Translated by Willpower,2004.1.4