数据的校验是交互式网站一个不可或缺的功能,前端的js校验可以涵盖大部分的校验职责,如用户名唯一性,生日格式,邮箱格式校验等等常用的校验。但是为了避免用户绕过浏览器,使用http工具直接向后端请求一些违法数据,服务端的数据校验也是必要的,可以防止脏数据落到数据库中。
SpringMVC自身对数据在服务端的校验有一个比较好的支持,它能将我们提交到服务端的数据按照我们事先的约定进行数据有效性验证,对于不合格的数据信息SpringMVC会把它保存在错误对象中,这些错误信息我们也可以通过SpringMVC提供的标签在前端JSP页面上进行展示。
步骤:
1.在实体类中添加验证
2.在html页面添加错误信息
3.在controller类中实现验证
4.更新验证的html页面
被校验的实体类
public class Customer {
private String firstName;
@NotNull(message="is required")
@Size(min=1, message="is required")
private String lastName;
@Min(value=0,message="Must be greater than or equal to zero")
@Max(value=10,message="Must be less than or equal to 10")
private int freePasses;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getFreePasses() {
return freePasses;
}
public void setFreePasses(int freePasses) {
this.freePasses = freePasses;
}
}
JSR提供的校验注解:
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式
Hibernate Validator提供的校验注解:
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内
@Controller
@RequestMapping("/customer")
public class CustomerController {
// add an initbinder ... to convert trim input strings
// remove leading and trailing whitespace
// resolve issue for our validation
@InitBinder
public void initBinderZ(WebDataBinder dataBinder) {
StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);
dataBinder.registerCustomEditor(String.class,stringTrimmerEditor);
}
@RequestMapping("/showForm")
public String showForm(Model theModel) {
theModel.addAttribute("customer", new Customer());
return "customer-form";
}
@RequestMapping("/processForm")
public String processForm(
@Valid @ModelAttribute("customer") Customer theCustomer,
BindingResult theBindingResult){
System.out.println("Last name: |"+theCustomer.getLastName()+"|");
if(theBindingResult.hasErrors())
return "customer-form";
else
return "customer-confirmation";
}
}
customer-form.jsp
<head>
<title>Customer Registration Formtitle>
<style>
.error {color:red}
style>
head>
<body>
<i>Fill out the form. Asterisk (*) means required.<i>
<form:form action="processForm" modelAttribute="customer">
First Name: <form:input path="firstName" />
<br><br>
Last Name(*): <form:input path="lastName" />
<form:errors path="lastName" cssClass="error" />
<br><br>
Free passes:<form:input path="freePasses"/>
<form:errors path="freePasses" cssClass="error" />
<br><br>
<input type="submit" value="Submit">
form:form>
body>
customer-confirmation.jsp
<!DOCTYPE html>
<html>
<head>
<title>Customer Confirmation</title>
</head>
<body>
The customer is confirmed:${customer.firstName } ${customer.lastName}
<br><br>
Free passes:${customer.freePasses }
</body>
</html>
上面是对于数字和输入是否为空的判定,那么如果需要对字符、数字以及指定字符数的验证怎么做呢?
验证类
@Pattern(regexp="^[a-zA-Z0-9]{5}", message="Only 5 chars/digits")
private String postalCode;
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
html展示页面
Postal Code:<form:input path="postalCode"/>
<form:errors path="postalCode" cssClass="error" />
<br><br>
当freePasses输入为null的时候,int类型的freePasses没有办法进行类型转换,解决办法是将它的数据类型体为integer。
private Integer freePasses;
public Integer getFreePasses() {
return freePasses;
}
public void setFreePasses(Integer freePasses) {
this.freePasses = freePasses;
}
/src/resources/messages.properties
typeMismatch.customer.freePasses=Invalid number
WebContent/WEB-INF/spring-mvc-demo-servlet.xml
<!-- Load custom message resources-->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="resources/messages" />
</bean>
为什么可以在properties文件里面这样写?
在controller类里面打印Binding result参数,发现其实在properties文件其实只是overide 它的default message为自定义的内容。
System.out.println("Binding result:" + theBindingResult);
Binding result:org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'customer' on field 'freePasses': rejected value [adfsggd]; codes [typeMismatch.customer.freePasses,typeMismatch.freePasses,typeMismatch.java.lang.Integer,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [customer.freePasses,freePasses]; arguments []; default message [freePasses]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.lang.Integer' for property 'freePasses'; nested exception is java.lang.NumberFormatException: For input string: "adfsggd"]