SpringMvc的数据校验
配置校验
<!--校验错误信息配置文件--> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource" p:basename="classpath:i18n/message" p:defaultEncoding="utf-8" p:cacheSeconds="120"/> //这里要使用defaultEncoding="utf-8",否则会出现乱码 <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <!--使用hibernate校验器--> <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/> <property name="validationMessageSource" ref="messageSource"/> </bean>
配置好了校验器后,需要将校验器注入到处理器适配器中
<mvc:annotation-driven conversion-service="conversionService" validator="validator"/>
hibernate校验框架提供注解校验


User的注解校验
@Pattern(regexp="\\w{4,10}")
private String userName;
@Pattern(regexp="\\w{5,10}")
private String password;
@Length(min=2,max=100)
private String realName;
@Past
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthday;
@DecimalMin(value="1000.00")
@DecimalMax(value="10000.00")
@NumberFormat(pattern = "#,###.#")
private long salary;
message_zh_CN.properties进行消息配置
userName.validator.error=用户名必须是至少4个到10个的字母数字下划线组成
password.validator.error=用户密码非空,至少5到10个字母数字组成
realName.validator.error=用户真实姓名无效,长度必须在2到100之间
birthday.validator.error=生日必须是一个过去的时间
salary.minValidator.error=用户的薪水至少大于1000
salary.maxValidator.error=用户的薪水至少小于一万
required.user.userName=用户名必须有
捕获错误逻辑
在需要校验的pojo前边添加@Validated,在需要校验的pojo后边添加BindingResult bindingResult来接收校验出错信息。值得注意的是:@Validated和BindingResult bindingResult是配对出现,并且形参顺序是固定的
@RequestMapping(value="/showUser",method= RequestMethod.POST) public ModelAndView showUser(@Valid User user,BindingResult bindingResult){ ModelAndView modelAndView = new ModelAndView(); if(bindingResult.hasErrors()){ modelAndView.setViewName("user/registerError"); return modelAndView; } modelAndView.addObject("user",user); userService.saveUser(user); modelAndView.setViewName("user/showUser"); return modelAndView; }
错误页面
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<html>
<head>
<title>注册用户</title>
<style>.errorClass{color:red}</style>
</head>
<body>
<form:form modelAttribute="user" action="${pageContext.request.contextPath}/user/register">
<form:errors path="*"/>
<table>
<tr>
<td>用户名</td>
<td>
<form:errors path="userName" cssClass="errorClass"/>
<br>
<form:input path="userName"/>
</td>
</tr>
<tr>
<td>密码</td>
<td>
<form:errors path="password" cssClass="errorClass"/>
<br>
<form:password path="password"/>
</td>
</tr>
<tr>
<td>姓名:</td>
<td>
<form:errors path="realName" cssClass="errorClass" element="div"/>
<br>
<form:input path="realName" />
</td>
</tr>
<tr>
<td>生日:</td>
<td>
<form:errors path="birthday" cssClass="errorClass" element="div"/>
<br>
<form:input path="birthday" />
</td>
</tr>
<tr>
<td>工资:</td>
<td>
<form:errors path="salary" cssClass="errorClass" element="div"/>
<br>
<form:input path="salary" />
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" name="提交"/>
</td>
</tr>
</table>
</form:form>
</body>
</html>
效果图

@Valid是使用hibernate validation对javax提供了@Valid(标准JSR-303规范)的实现
@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验
Spring Validation验证框架对参数的验证机制提供@Validated(Spring's JSR-303规范,是标准JSR-303的一个变种)
分组
@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制,@Valid:作为标准JSR-303规范,还没有吸收分组的功能
注解地方
@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上
两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能
嵌套验证
实体Item
public class Item { @NotNull(message = "id不能为空") @Min(value = 1, message = "id必须为正整数") private Long id; @NotNull(message = "props不能为空") @Size(min = 1, message = "至少要有一个属性") private List<Prop> props; }
Item的Prop对象
public class Prop { @NotNull(message = "pid不能为空") @Min(value = 1, message = "pid必须为正整数") private Long pid; @NotNull(message = "vid不能为空") @Min(value = 1, message = "vid必须为正整数") private Long vid; @NotBlank(message = "pidName不能为空") private String pidName; @NotBlank(message = "vidName不能为空") private String vidName; }
ItemController接受一个Item的入参,想要对Item进行验证,如下所示:
@RestController public class ItemController { @RequestMapping("/item/add") public void addItem(@Validated Item item, BindingResult bindingResult) { doSomething(); } }
如果Item实体的props属性不额外加注释,只有@NotNull和@Size,无论入参采用@Validated还是@Valid验证,Spring Validation框架只会对Item的id和props做非空和数量验证,不会对props字段里的Prop实体进行字段验证,也就是@Validated和@Valid加在方法参数前,都不会自动对参数进行嵌套验证。如果传的List<Prop>中有Prop的pid为空或者是负数,入参验证不会检测出来。
为了能够进行嵌套验证,必须手动在Item实体的props字段上明确指出这个字段里面的实体也要进行验证。由于@Validated不能用在成员属性(字段)上,但是@Valid能加在成员属性(字段)上,而且@Valid类注解上也说明了它支持嵌套验证功能,那么我们能够推断出:@Valid加在方法参数时并不能够自动进行嵌套验证,而是用在需要嵌套验证类的相应字段上,来配合方法参数上@Validated或@Valid来进行嵌套验证。
public class Item { @NotNull(message = "id不能为空") @Min(value = 1, message = "id必须为正整数") private Long id; @Valid // 嵌套验证必须用@Valid @NotNull(message = "props不能为空") @Size(min = 1, message = "props至少要有一个自定义属性") private List<Prop> props; }
在ItemController的addItem函数上,再使用@Validated或者@Valid,就能对Item的入参进行嵌套验证。此时Item里面的props如果含有Prop的相应字段为空的情况,Spring Validation框架就会检测出来,bindingResult就会记录相应的错误。
总结一下@Validated和@Valid在嵌套验证功能上的区别:
@Validated:用在方法入参上无法单独提供嵌套验证功能。不能用在成员属性(字段)上,也无法提示框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。
@Valid:用在方法入参上无法单独提供嵌套验证功能。能够用在成员属性(字段)上,提示验证框架进行嵌套验证。能配合嵌套验证注解@Valid进行嵌套验证。
参考:
https://blog.csdn.net/eson_15/article/details/51725470
https://blog.csdn.net/qq_27680317/article/details/79970590
浙公网安备 33010602011771号