在 Web 应用程序中,为了防止客户端传来的数据引发程序的异常,常常需要对数据进行验证。
输入验证分为客户端验证与服务器端验证。客户端验证主要通过 JavaScript 脚本进 行,
而服务器端验证则主要是通过 Java 代码进行验证。
为了保证数据的安全性,一般情况下,客户端验证与服务器端验证都是要进行的。
我们这里所讲的是 SpringMVC 在服务端是如何对数据进行验证的。
搭建测试环境
1.导入Jar包
SpringMVC 支持 JSR(Java Specification Requests,Java 规范提案)303 - Bean Validation数据验证规范。
而该规范的实现者很多,其中较常用的是 Hibernate Validator。需要注意的是, Hibernate Validator 是与
Hibernate ORM 并列的 Hibernate 的产品之一。这一点从 Hibernate 官 网上所提供的资源形式可以看出它们之间的关系。
所以,除了 SpringMVC 的 Jar 包外,我们还需要导入 Hibernate Validator 的 Jar 包。
这些Jar 包,可以从 Hibernate 官网中直接下载
实现数据验证
1.修改springmvc配置文件
验证器由SpringMVC框架的LocalValidtorFactoryBean类生成,而真正验证器的提供者是HibernateValidator
在SpringMVC 配置文件中 将验证器注册后,需要将其注入给注解驱动
1 <!-- 验证器 由 SpringMVC框架的 LocalValidtorFactoryBean 类生成 ,而真正的验证器的提供者 则是 HibernateValidator --> 2 <!-- 验证器注册完成后,需要将其注入给注解驱动 --> 3 4 <!-- 注册验证器 --> 5 <bean id="myValidator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> 6 <property name="providerClass" value="org.hibernate.validator.HibernateValidator"></property> 7 </bean> 8 9 <mvc:annotation-driven validator="myValidator"/>
2.在实体属性上添加验证注解
使用的验证器注解均是 javax.validation.constraints包中的类
在注解的message属性中,可以使用 {属性名}的方式来引用指定的注解的属性值
1 //在实体属性上添加验证注解 2 //使用的验证注解 均为 javax.validation.constraints 3 //在注解的 message(不满足验证条件后的返回的提示信息) 中,可以使用 {属性名} 的方式,来引用属性的 值 4 public class Person { 5 @NotEmpty(message="用户名不能为空") 6 @Size(min=3,max=6,message="用户名长度应为 {min} - {max}位") 7 private String name; 8 9 @Max(value=100,message="分数不能超过 {value}") 10 @Min(value=0,message="分数不能低于 {value}") 11 private double score; 12 13 @NotEmpty(message="手机号不能为空") 14 @Pattern(regexp="^1[34578]\\d{9}$",message="手机号码格式不正确") 15 private String phoneNumber; 16 public String getName() { 17 return name; 18 }
NotNull 和 NotEmpty区别:
NotNull:验证注解的元素值不为 null
NotEmpty:验证注解的元素值不为 null 且不为空(字符串长度不为 0、集合大小不为 0)
3.修改Controller
1 public class MyController { 2 3 4 // 数据验证 5 //由于这里使用的 验证器为 Bean 对象验证器,所以对于要验证的参数数据,需是一个Bean 类型,使用 @Validated 标记这是要检验的 Bean 6 //注: 不能将 @Validated 注解在String类型与基本类型的形参前 7 // 通过 BindingResult 形参 可以获取到所有验证异常信息 (message 里面的) 8 @RequestMapping(value = "/validator.do") 9 public ModelAndView register(@Validated Person person,BindingResult br) { 10 ModelAndView mv = new ModelAndView(); 11 //获取到所有的异常信息,如果没有异常,List也不会 为 null,而是 size = 0; 12 List<ObjectError> errors = br.getAllErrors(); 13 System.out.println(errors.size()); 14 //如果存在验证异常 15 if(errors.size()>0) { 16 //获取指定属性的异常信息 17 FieldError nameError = br.getFieldError("name"); 18 FieldError scoreError = br.getFieldError("score"); 19 FieldError phoneNumberError = br.getFieldError("phoneNumber"); 20 21 //哪个FileError 不为空(即该属性不符合验证条件),则将对应的错误信息存入ModelAndView 22 if(nameError != null) { 23 24 //如果不满足多个验证条件,如:不填 同时不满足 (1、不为空,2、3-6字符,)错误信息好像随机选一个的 25 mv.addObject("nameError", nameError.getDefaultMessage()); 26 } 27 if(scoreError != null) { 28 mv.addObject("scoreError", scoreError.getDefaultMessage()); 29 } 30 if(phoneNumberError != null) { 31 mv.addObject("phoneNumberError", phoneNumberError.getDefaultMessage()); 32 } 33 mv.setViewName("/index.jsp"); 34 return mv; 35 } 36 mv.addObject("person", person); 37 mv.setViewName("/WEB-INF/jsp/hello.jsp"); 38 return mv; 39 40 } 41 42 }
BindingResult 接口中常用的方法有:
getAllErrors():获取到所有的异常信息。其返回值为List,若没有发生异常,则该List也被创建,
只不过其size()为0,而非List为null
getFieldError():获取指定属性的异常信息
getErrorCount(): 获取所有异常的数量
getRawFieldValue():获取到用户输入的引发验证异常的原始值
4.页面显示异常信息
1 <form action="${pageContext.request.contextPath }/test/validator.do" method="post"> 2 name :<input name="name" type="text"/> ${nameError }<br/> 3 score : <input name="score" type="text"/>${scoreError }<br/> 4 phoneNumber: <input name="phoneNumber" type="text"/>${phoneNumberError }<br/> 5 <input type="submit" value="提交"/> 6 </form>