下面给一个在Spring 中使用common-validator进行表单验证的小例子
1.POJO:
public class Book {
String id;
String name;
String author;
String price;
public Book(){
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String toString(){
return "\nid: " + id + "\nname: " + name + "\nauthor: " + author + "\nprice: " + price;
}
}
2.Controller, 这个controller要继承自支持validation的controller,最典型的就是SimpleFormController.
public class BookController extends SimpleFormController{
@Override
protected ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
Book book = (Book)command;
System.out.println(book);
return super.onSubmit(request, response, command, errors);
}
}
3.在bean config文件里定义两个bean:validatorFactory,beanValidator(写法参见代码)。
<bean id="validatorFactory" class="org.springmodules.commons.validator.DefaultValidatorFactory">
<property name="validationConfigLocations">
<list>
<value>WEB-INF/spring-validator-rules.xml</value>
<value>WEB-INF/validation.xml</value>
</list>
</property>
</bean>
<bean id="beanValidator" class="org.springmodules.commons.validator.DefaultBeanValidator">
<property name="validatorFactory" ref="validatorFactory"/>
</bean>
4.定义Controller bean: /addBook.do(写法参见代码) 有一点要强调:commandName不可以随便写,比如本例中commandClass是model.Book,:commandName如果写成bookForm会出错。必须写成首字母小写:book.
<bean name="/addbook.do" class="action.BookController">
<property name="commandName" value="book" />
<property name="commandClass" value="model.Book"/>
<property name="formView" value="addbook.jsp" />
<property name="successView" value="addbook.jsp" />
<property name="validator" ref="beanValidator" />
</bean>
5.编写或拷贝 messages.properties.注意以errors.开头的message在显示验证出错的时候会用到。你可以根据具体情况修改语境。以book.XXXX.displayName类似的消息是和具体的form相关的消息。比如book.name.displayName=Book Name这个,在下面validation.xml的book form中使用到则如果书名出错,则会显示Book Name is required.
注意: 该文件要放在classpath下面.而且如果浏览器语言是中文的, 则要把文件名称改为messages_zh_CN.properties.
errors.required={0} is required.
errors.minlength={0} can not be less than {1} characters.
errors.maxlength={0} can not be greater than {1} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.
errors.float={0} must be a float.
errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is an invalid credit card number.
errors.email={0} is an invalid e-mail address.
common.messages.close=Close
book.id.displayName=Id
book.name.displayName=Book Name
book.author.displayName=Author
book.price.displayName=Price
6.配置messageSource
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages" />
</bean>
7.拷贝或编写spring-validator-rules.xml到WEB-INF.里面定义了一些validator,你也可以自己添加。这个文件我想既然spring使用的是struts验证框架的plag-in, 则struts中有这个文件.
8.编写WEB-INF/validation.xml,这里面定义了一些常量和form 的validation规则。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1//EN" "http://jakarta.apache.org/commons/dtds/validator_1_1.dtd">
<form-validation>
<global>
<constant>
<constant-name>number</constant-name>
<constant-value>^\d+$</constant-value>
</constant>
<constant>
<constant-name>englishName</constant-name>
<constant-value>^[A-Z0-9a-z\s]+$</constant-value>
</constant>
<constant>
<constant-name>invalidCharacter</constant-name>
<constant-value><![CDATA[$%'*+:;<=>?@^_`{|}]]></constant-value>
</constant>
<constant>
<constant-name>invalidDiscussionCharacter</constant-name>
<constant-value><![CDATA[$%'*+;<=>?@^_`{|}]]></constant-value>
</constant>
<constant>
<constant-name>validDiscussionCharacterReguler</constant-name>
<constant-value><![CDATA[^[^${invalidCharacterForFilter}]*$]]></constant-value>
</constant>
<constant>
<constant-name>invalidBulletinBoardCharacter</constant-name>
<constant-value><![CDATA[$<>^`|]]></constant-value>
</constant>
<constant>
<constant-name>validBulletinBoardCharacterReguler</constant-name>
<constant-value><![CDATA[^[^${invalidBulletinBoardCharacter}]*$]]></constant-value>
</constant>
<constant>
<constant-name>invalidEmailCharacter</constant-name>
<constant-value><![CDATA[$%'*+:;<=>?^_`{|}]]></constant-value>
</constant>
<constant>
<constant-name>validCharacterReguler</constant-name>
<constant-value><![CDATA[^[^${invalidCharacter}]*$]]></constant-value>
</constant>
<constant>
<constant-name>validEmail</constant-name>
<constant-value><![CDATA[^[^${invalidEmailCharacter}]*$]]></constant-value>
</constant>
<constant>
<constant-name>defaultDateFormat</constant-name>
<constant-value><![CDATA[MM/dd/yyyy]]></constant-value>
</constant>
<constant>
<constant-name>invalidCharacterForFilter</constant-name>
<constant-value><![CDATA[$%'*:'<=>^`{|}]]></constant-value>
</constant>
<constant>
<constant-name>validCharacterRegulerForFilter</constant-name>
<constant-value><![CDATA[^[^${invalidCharacterForFilter}]*$]]></constant-value>
</constant>
</global>
<formset>
<form name="book">
<field property="id" depends="maxlength,required">
<arg0 key="book.id.displayName" />
<arg1 name="maxlength" key="${var:maxlength}" resource="false" />
<var>
<var-name>maxlength</var-name>
<var-value>10</var-value>
</var>
</field>
<field property="name" depends="maxlength,required">
<arg0 key="book.name.displayName" />
<arg1 name="maxlength" key="${var:maxlength}" resource="false" />
<var>
<var-name>maxlength</var-name>
<var-value>10</var-value>
</var>
</field>
<field property="author" depends="maxlength">
<arg0 key="book.author.displayName" />
<arg1 name="maxlength" key="${var:maxlength}" resource="false" />
<var>
<var-name>maxlength</var-name>
<var-value>5</var-value>
</var>
</field>
<field property="price" depends="mask">
<arg0 key="book.price.displayName" />
<arg1 name="number" key="${var:mask}" resource="false" />
<var>
<var-name>mask</var-name>
<var-value>^[0-9]</var-value>
</var>
</field>
</form>
</formset>
</form-validation>
9 写jsp页面也就是刚才在controller中配置的formView。注意用<spring:bind path="book.xxx">绑订字段。用value="<core:out value="${book.id}"/>"输出上次输入的值。在该页引入messages.jsp用于显示出错消息。
<!--addbook.jsp-->
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="WEB-INF/tld/spring-form.tld" prefix="form"%>
<%@ taglib uri="WEB-INF/tld/c-rt.tld" prefix="core"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
<script type="text/javascript" src=""></script>
<style type="text/css">
</style>
</head>
<body>
<%@ include file="messages.jsp" %>
<form method="post" action="addbook.do">
<spring:bind path="book.id">
<input type="text" name="id" value="<core:out value="${book.id}"/>"/>
</spring:bind>
<spring:bind path="book.name">
<input type="text" name="name" value="<core:out value="${book.name}"/>"/>
</spring:bind>
<spring:bind path="book.author">
<input type="text" name="author" value="<core:out value="${book.author}"/>"/>
</spring:bind>
<spring:bind path="book.price">
<input type="text" name="price" value="<core:out value="${book.price}"/>"/>
</spring:bind>
<input type="submit" value="Google" /><br>
</form>
</body>
</html>
10 写messages.jsp 注意image路径。
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="WEB-INF/tld/c-rt.tld" prefix="core"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<SCRIPT LANGUAGE=javascript>
function hideMessage() {
if ( messageTR.style.display == "") {
messageTR.style.display = "none";
}
}
</SCRIPT>
<spring:bind path="book.*">
<core:if test="${not empty status.errorMessages}">
<%
if(request.getAttribute("errors") == null){
List errors = new ArrayList();
request.setAttribute("errors",errors);
}
%>
<core:forEach var="error" items="${status.errorMessages}">
<%List errors = ((List)request.getAttribute("errors"));
errors.add(pageContext.getAttribute("error"));
%>
</core:forEach>
</core:if>
</spring:bind>
<core:if test="${not empty errors or not empty messages}">
<table border=0 cellpadding=0 cellspacing=0 width="95%" align="center">
<tr id='messageTR' style="DISPLAY:">
<td align="center">
<core:if test="${not empty errors}">
<core:set var="hasMessage" value="true"/>
<div align="left" class="error fade-ffff00" id="error">
<core:forEach var="error" items="${errors}">
<img src="<%=request.getContextPath()%>/images/iconWarning.gif" alt='Warning' class="icon" />
<core:out value="${error}" escapeXml="false"/><br/>
</core:forEach>
</div>
<core:remove var="errors"/>
</core:if>
<core:if test="${not empty messages}">
<core:set var="hasMessage" value="true"/>
<div align="left" class="message fade-ffff00" id="message">
<core:forEach var="msg" items="${messages}">
<img src="<%=request.getContextPath()%>/images/iconInformation.gif" alt='Information' class="icon" />
<core:out value="${msg}" escapeXml="false"/><br/>
</core:forEach>
</div>
<core:remove var="messages"/>
</core:if>
<core:if test="${hasMessage eq 'true'}"><a href="javascript:hideMessage();"> <spring:message code="common.messages.close"/> </a></core:if>
</td>
</tr>
</table>
</core:if>
1.POJO:
public class Book {
String id;
String name;
String author;
String price;
public Book(){
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String toString(){
return "\nid: " + id + "\nname: " + name + "\nauthor: " + author + "\nprice: " + price;
}
}
2.Controller, 这个controller要继承自支持validation的controller,最典型的就是SimpleFormController.
public class BookController extends SimpleFormController{
@Override
protected ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception {
Book book = (Book)command;
System.out.println(book);
return super.onSubmit(request, response, command, errors);
}
}
3.在bean config文件里定义两个bean:validatorFactory,beanValidator(写法参见代码)。
<bean id="validatorFactory" class="org.springmodules.commons.validator.DefaultValidatorFactory">
<property name="validationConfigLocations">
<list>
<value>WEB-INF/spring-validator-rules.xml</value>
<value>WEB-INF/validation.xml</value>
</list>
</property>
</bean>
<bean id="beanValidator" class="org.springmodules.commons.validator.DefaultBeanValidator">
<property name="validatorFactory" ref="validatorFactory"/>
</bean>
4.定义Controller bean: /addBook.do(写法参见代码) 有一点要强调:commandName不可以随便写,比如本例中commandClass是model.Book,:commandName如果写成bookForm会出错。必须写成首字母小写:book.
<bean name="/addbook.do" class="action.BookController">
<property name="commandName" value="book" />
<property name="commandClass" value="model.Book"/>
<property name="formView" value="addbook.jsp" />
<property name="successView" value="addbook.jsp" />
<property name="validator" ref="beanValidator" />
</bean>
5.编写或拷贝 messages.properties.注意以errors.开头的message在显示验证出错的时候会用到。你可以根据具体情况修改语境。以book.XXXX.displayName类似的消息是和具体的form相关的消息。比如book.name.displayName=Book Name这个,在下面validation.xml的book form中使用到则如果书名出错,则会显示Book Name is required.
注意: 该文件要放在classpath下面.而且如果浏览器语言是中文的, 则要把文件名称改为messages_zh_CN.properties.
errors.required={0} is required.
errors.minlength={0} can not be less than {1} characters.
errors.maxlength={0} can not be greater than {1} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.
errors.float={0} must be a float.
errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is an invalid credit card number.
errors.email={0} is an invalid e-mail address.
common.messages.close=Close
book.id.displayName=Id
book.name.displayName=Book Name
book.author.displayName=Author
book.price.displayName=Price
6.配置messageSource
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="messages" />
</bean>
7.拷贝或编写spring-validator-rules.xml到WEB-INF.里面定义了一些validator,你也可以自己添加。这个文件我想既然spring使用的是struts验证框架的plag-in, 则struts中有这个文件.
8.编写WEB-INF/validation.xml,这里面定义了一些常量和form 的validation规则。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1//EN" "http://jakarta.apache.org/commons/dtds/validator_1_1.dtd">
<form-validation>
<global>
<constant>
<constant-name>number</constant-name>
<constant-value>^\d+$</constant-value>
</constant>
<constant>
<constant-name>englishName</constant-name>
<constant-value>^[A-Z0-9a-z\s]+$</constant-value>
</constant>
<constant>
<constant-name>invalidCharacter</constant-name>
<constant-value><![CDATA[$%'*+:;<=>?@^_`{|}]]></constant-value>
</constant>
<constant>
<constant-name>invalidDiscussionCharacter</constant-name>
<constant-value><![CDATA[$%'*+;<=>?@^_`{|}]]></constant-value>
</constant>
<constant>
<constant-name>validDiscussionCharacterReguler</constant-name>
<constant-value><![CDATA[^[^${invalidCharacterForFilter}]*$]]></constant-value>
</constant>
<constant>
<constant-name>invalidBulletinBoardCharacter</constant-name>
<constant-value><![CDATA[$<>^`|]]></constant-value>
</constant>
<constant>
<constant-name>validBulletinBoardCharacterReguler</constant-name>
<constant-value><![CDATA[^[^${invalidBulletinBoardCharacter}]*$]]></constant-value>
</constant>
<constant>
<constant-name>invalidEmailCharacter</constant-name>
<constant-value><![CDATA[$%'*+:;<=>?^_`{|}]]></constant-value>
</constant>
<constant>
<constant-name>validCharacterReguler</constant-name>
<constant-value><![CDATA[^[^${invalidCharacter}]*$]]></constant-value>
</constant>
<constant>
<constant-name>validEmail</constant-name>
<constant-value><![CDATA[^[^${invalidEmailCharacter}]*$]]></constant-value>
</constant>
<constant>
<constant-name>defaultDateFormat</constant-name>
<constant-value><![CDATA[MM/dd/yyyy]]></constant-value>
</constant>
<constant>
<constant-name>invalidCharacterForFilter</constant-name>
<constant-value><![CDATA[$%'*:'<=>^`{|}]]></constant-value>
</constant>
<constant>
<constant-name>validCharacterRegulerForFilter</constant-name>
<constant-value><![CDATA[^[^${invalidCharacterForFilter}]*$]]></constant-value>
</constant>
</global>
<formset>
<form name="book">
<field property="id" depends="maxlength,required">
<arg0 key="book.id.displayName" />
<arg1 name="maxlength" key="${var:maxlength}" resource="false" />
<var>
<var-name>maxlength</var-name>
<var-value>10</var-value>
</var>
</field>
<field property="name" depends="maxlength,required">
<arg0 key="book.name.displayName" />
<arg1 name="maxlength" key="${var:maxlength}" resource="false" />
<var>
<var-name>maxlength</var-name>
<var-value>10</var-value>
</var>
</field>
<field property="author" depends="maxlength">
<arg0 key="book.author.displayName" />
<arg1 name="maxlength" key="${var:maxlength}" resource="false" />
<var>
<var-name>maxlength</var-name>
<var-value>5</var-value>
</var>
</field>
<field property="price" depends="mask">
<arg0 key="book.price.displayName" />
<arg1 name="number" key="${var:mask}" resource="false" />
<var>
<var-name>mask</var-name>
<var-value>^[0-9]</var-value>
</var>
</field>
</form>
</formset>
</form-validation>
9 写jsp页面也就是刚才在controller中配置的formView。注意用<spring:bind path="book.xxx">绑订字段。用value="<core:out value="${book.id}"/>"输出上次输入的值。在该页引入messages.jsp用于显示出错消息。
<!--addbook.jsp-->
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="WEB-INF/tld/spring-form.tld" prefix="form"%>
<%@ taglib uri="WEB-INF/tld/c-rt.tld" prefix="core"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP 'index.jsp' starting page</title>
<script type="text/javascript" src=""></script>
<style type="text/css">
</style>
</head>
<body>
<%@ include file="messages.jsp" %>
<form method="post" action="addbook.do">
<spring:bind path="book.id">
<input type="text" name="id" value="<core:out value="${book.id}"/>"/>
</spring:bind>
<spring:bind path="book.name">
<input type="text" name="name" value="<core:out value="${book.name}"/>"/>
</spring:bind>
<spring:bind path="book.author">
<input type="text" name="author" value="<core:out value="${book.author}"/>"/>
</spring:bind>
<spring:bind path="book.price">
<input type="text" name="price" value="<core:out value="${book.price}"/>"/>
</spring:bind>
<input type="submit" value="Google" /><br>
</form>
</body>
</html>
10 写messages.jsp 注意image路径。
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib uri="WEB-INF/tld/c-rt.tld" prefix="core"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<SCRIPT LANGUAGE=javascript>
function hideMessage() {
if ( messageTR.style.display == "") {
messageTR.style.display = "none";
}
}
</SCRIPT>
<spring:bind path="book.*">
<core:if test="${not empty status.errorMessages}">
<%
if(request.getAttribute("errors") == null){
List errors = new ArrayList();
request.setAttribute("errors",errors);
}
%>
<core:forEach var="error" items="${status.errorMessages}">
<%List errors = ((List)request.getAttribute("errors"));
errors.add(pageContext.getAttribute("error"));
%>
</core:forEach>
</core:if>
</spring:bind>
<core:if test="${not empty errors or not empty messages}">
<table border=0 cellpadding=0 cellspacing=0 width="95%" align="center">
<tr id='messageTR' style="DISPLAY:">
<td align="center">
<core:if test="${not empty errors}">
<core:set var="hasMessage" value="true"/>
<div align="left" class="error fade-ffff00" id="error">
<core:forEach var="error" items="${errors}">
<img src="<%=request.getContextPath()%>/images/iconWarning.gif" alt='Warning' class="icon" />
<core:out value="${error}" escapeXml="false"/><br/>
</core:forEach>
</div>
<core:remove var="errors"/>
</core:if>
<core:if test="${not empty messages}">
<core:set var="hasMessage" value="true"/>
<div align="left" class="message fade-ffff00" id="message">
<core:forEach var="msg" items="${messages}">
<img src="<%=request.getContextPath()%>/images/iconInformation.gif" alt='Information' class="icon" />
<core:out value="${msg}" escapeXml="false"/><br/>
</core:forEach>
</div>
<core:remove var="messages"/>
</core:if>
<core:if test="${hasMessage eq 'true'}"><a href="javascript:hideMessage();"> <spring:message code="common.messages.close"/> </a></core:if>
</td>
</tr>
</table>
</core:if>