<
spring:bind
path
="command.name"
>
name:
<
input
type
="text"
name
="name"
value
="<c:out value="
${status.value}"
/>
"/>(必须输入)
<
c:if
test
="${status.error}"
>
<
font
color
="#FF0000"
>
错误:
<
c:forEach
items
="${status.errorMessages}"
var
="error"
>
<
c:out
value
="${error}"
/>
</
c:forEach
>
</
font
>
</
c:if
>
</
spring:bind
>
<
spring:bind
path
="command.name"
>
name:
<
input
type
="text"
name
="name"
value
="<c:out value="
${status.value}"
/>
"/>(必须输入)
<
c:if
test
="${status.error}"
>
<
font
color
="#FF0000"
>
错误:
<
c:forEach
items
="${status.errorMessages}"
var
="error"
>
<
c:out
value
="${error}"
/>
</
c:forEach
>
</
font
>
</
c:if
>
</
spring:bind
>
Spring MVC为我们提供了类似struts validator的验证框架,但spring并非编写xml验证文件,而且是实现期自身提供的Validator接口,为我们的POJO javabean提供针对具体类的验证,非常方便,下面,我们就一起来实现这个功能
首先,我们先编写一个注册页面,只有两个字段,姓名和性别,这里要求姓名和性别都必须输入,而且性别只能输入0或1
register.jsp
<%
...
@ page language="java" import="java.util.*" pageEncoding="GB18030"
%>
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
<%
...
@ taglib prefix="spring" uri="http://www.springframework.org/tags"
%>
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
<%
...
@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"
%>
<!
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
>
<
html
>
<
head
>
</
head
>
<
body
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<
spring:bind
path
="command.*"
>
<
font
color
="#FF0000"
>
<
c:forEach
items
="${status.errorMessages}"
var
="error"
>
错误:
<
c:out
value
="${error}"
/><
br
>
</
c:forEach
>
</
font
>
</
spring:bind
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<
form
action
="<%=request.getContextPath() %>/register.mvc"
method
="post"
>
<
spring:bind
path
="command.name"
>
name:
<
input
type
="text"
name
="name"
value
="<c:out value="
${status.value}"
/>
"/>(必须输入)
<
c:if
test
="${status.error}"
>
<
font
color
="#FF0000"
>
错误:
<
c:forEach
items
="${status.errorMessages}"
var
="error"
>
<
c:out
value
="${error}"
/>
</
c:forEach
>
</
font
>
</
c:if
>
</
spring:bind
></
br
>
<
spring:bind
path
="command.sex"
>
sex:
<
input
type
="text"
name
="sex"
/>
(必须输入,且为0或1)
<
c:if
test
="${status.error}"
>
<
font
color
="#FF0000"
>
错误:
<
c:forEach
items
="${status.errorMessages}"
var
="error"
>
<
c:out
value
="${error}"
/>
</
c:forEach
>
</
font
>
</
c:if
>
</
spring:bind
></
br
>
<
input
type
="submit"
value
="submit"
/>
</
form
>
</
body
>
</
html
>
其中关于Spring bind标签和jstl标签可以先暂时忽略,后面酱油详细介绍
然后编写我们的表单对应POJO JavaBean
Student.java
package
model;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
public
class
Student
...
{
private String name;
private String sex;
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public String getName() ...{
return name;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void setName(String name) ...{
this.name = name;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public String getSex() ...{
return sex;
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void setSex(String sex) ...{
this.sex = sex;
}
}
编写我们的控制器controller
RegisterStudentController.java
这个控制室是在我们通过验证后,将表单输入的内容显示在一个成功页面中,页面逻辑名用getSuccessView()获得,从spring配置文件中注入
package
Action;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
import
model.Student;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
import
org.springframework.validation.BindException;
import
org.springframework.web.servlet.ModelAndView;
import
org.springframework.web.servlet.mvc.SimpleFormController;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
public
class
RegisterStudentController
extends
SimpleFormController
...
{
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public RegisterStudentController()...{
this.setCommandClass(Student.class);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
protected ModelAndView onSubmit(Object object, BindException arg1) throws Exception ...{
Student stu=(Student)object;
return new ModelAndView(getSuccessView(),"student",stu);
}
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
}
线面编写我们的
验证根据errors对象返回错误,我们有两种定制errors的方法
(1) errors.rejectValue("name","notnull",null, "用户名长度必须输入!");
rejectVlaue方法有4个参数:
1. Error Code 显示错误时,将根据错误代码识别错误信息类型。
2. Message Key上面关于ApplicationContext 的国际化支持时, 我们曾经谈及MessageSource的使用,
这里我们可以通过引入MessageSource实现提示信息的参数化,此时,本参数将用作.properties文件
中的消息索引。
3. Error Argument 如果提示信息中需要包含动态信息,则可通过此参数传递需要的动态信息对象。具
体参见ApplicationContext中关于国际化实现的描述。
4. Default Message
如果在当前MessageSource中没有发现Message Key对应的信息数据,则以此默认值返回。
这里我们暂时尚未考虑国际化支持,所有的信息都将通过Default Message返回
(2) ValidationUtils.rejectIfEmpty(errors, "name", "name", "姓名必须输入");
package
model;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
import
org.apache.oro.text.perl.Perl5Util;
import
org.springframework.validation.Errors;
import
org.springframework.validation.ValidationUtils;
import
org.springframework.validation.Validator;
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
public
class
StudentValidator
implements
Validator
...
{
private static String SEX_REGEXP="/^[0-1]$/";
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public boolean supports(Class cls) ...{
return cls.equals(Student.class);
}
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
public void validate(Object object, Errors errors) ...{
Student student=(Student)object;
// if(student.getName().equals("")||student.getName()==null){
// errors.rejectValue("name",
// "notnull",
// null,
// "用户名长度必须输入!");
// }
ValidationUtils.rejectIfEmpty(errors, "name", "name", "姓名必须输入");
ValidationUtils.rejectIfEmpty(errors, "sex", "sex", "性别必须输入");
Perl5Util perl5Util=new Perl5Util();
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
if(!perl5Util.match(SEX_REGEXP, student.getSex()))...{
errors.rejectValue("sex", "not confirmat", null,"性别格式错误");
}
}
}
其中一下部分是用ORO正则表达式验证类库进行sex字段的正则验证
if
(
!
perl5Util.match(SEX_REGEXP, student.getSex()))
...
{
errors.rejectValue("sex", "not confirmat", null,"性别格式错误");
}
配置文件:
web.xml
<?
xml version="1.0" encoding="UTF-8"
?>
<
web-app
version
="2.4"
xmlns
="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
>
<
context-param
>
<
param-name
>
contextConfigLocation
</
param-name
>
<
param-value
>
/WEB-INF/train-servlet.xml
</
param-value
>
</
context-param
>
<
servlet
>
<
servlet-name
>
train
</
servlet-name
>
<
servlet-class
>
org.springframework.web.servlet.DispatcherServlet
</
servlet-class
>
<
load-on-startup
>
0
</
load-on-startup
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>
train
</
servlet-name
>
<
url-pattern
>
*.mvc
</
url-pattern
>
</
servlet-mapping
>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<
listener
>
<
listener-class
>
org.springframework.web.context.ContextLoaderListener
</
listener-class
>
</
listener
>
<
filter
>
<
filter-name
>
character
</
filter-name
>
<
filter-class
>
Action.CharacterFilter
</
filter-class
>
</
filter
>
<
filter-mapping
>
<
filter-name
>
character
</
filter-name
>
<
url-pattern
>
/*
</
url-pattern
>
</
filter-mapping
>
<
welcome-file-list
>
<
welcome-file
>
index.jsp
</
welcome-file
>
</
welcome-file-list
>
</
web-app
>
train-servlet.xml
我们用
<property name="validator">
<bean class="model.StudentValidator"></bean>
</property>
来定义验证类
用
<property name="commandClass">
<value>model.Student</value>
</property>
来定义验证框架需要验证的类(这个属性对我们在页面上显示错误信息有用)
<
bean
id
="RegisterStudentController"
class
="Action.RegisterStudentController"
>
<
property
name
="commandClass"
>
<
value
>
model.Student
</
value
>
</
property
>
<
property
name
="formView"
>
<
value
>
register
</
value
>
</
property
>
<
property
name
="successView"
>
<
value
>
success
</
value
>
</
property
>
<
property
name
="validator"
>
<
bean
class
="model.StudentValidator"
></
bean
>
</
property
>
</
bean
>
<
bean
id
="simpleUrlMapping"
class
="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"
>
<
property
name
="mappings"
>
<
props
>
<
prop
key
="/register.mvc"
>
RegisterStudentController
</
prop
>
</
props
>
</
property
>
</
bean
>
线面说明一下registe.jsp的两端代码
(1)
用spring:bind标签绑定Student类(由于在配置文件中配置了commandClass),我们在这里可以使用command.*代替Student.*,使用jstl迭代显示出errors对象中的所有错误信息
<
spring:bind
path
="command.*"
>
<
font
color
="#FF0000"
>
<
c:forEach
items
="${status.errorMessages}"
var
="error"
>
错误:
<
c:out
value
="${error}"
/><
br
>
</
c:forEach
>
</
font
>
</spring:bind>
(2)
使用spring帮顶student的name属性,如果其error对象不为空,则单独显示这个属性的error信息
<
spring:bind
path
="command.name"
>
name:
<
input
type
="text"
name
="name"
value
="<c:out value="
${status.value}"
/>
"/>(必须输入)
<
c:if
test
="${status.error}"
>
<
font
color
="#FF0000"
>
错误:
<
c:forEach
items
="${status.errorMessages}"
var
="error"
>
<
c:out
value
="${error}"
/>
</
c:forEach
>
</
font
>
</
c:if
>
</
spring:bind
>
最后一个是个注册成功页面 success.jsp
<%
...
@ page language="java" import="java.util.*" pageEncoding="GB18030"
%>
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
<%
...
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
<!
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
>
<
html
>
<
head
>
<
base
href
="<%=basePath%>"
>
<
title
>
My JSP 'index.jsp' starting page
</
title
>
<
meta
http-equiv
="pragma"
content
="no-cache"
>
<
meta
http-equiv
="cache-control"
content
="no-cache"
>
<
meta
http-equiv
="expires"
content
="0"
>
<
meta
http-equiv
="keywords"
content
="keyword1,keyword2,keyword3"
>
<
meta
http-equiv
="description"
content
="This is my page"
>
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</
head
>
<
body
>
${student.name}-----${student.sex}
<
br
>
</
body
>
</
html
>
值得注意的是:我们要从register.mvc来启动程序,转发到register.jsp(配置文件中的fromView属性配置),否则spring:bind标签会出现如下异常:
Neither BindingResult nor plain target object for bean name 'command' available as request attribute
部署,运行
(1)不输入姓名和性别,页面如下:
错误: 姓名必须输入
错误: 性别必须输入
错误: 性别格式错误
(2)输入姓名,不输入性别,页面如下:
错误: 性别必须输入
错误: 性别格式错误
(3)不输入姓名,输入正确性别,页面如下:
错误: 姓名必须输入
(4)输入姓名,输入错误性别,页面如下:
错误: 性别格式错误
(5)都正确输入,页面如下:
11-----1