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 

posted on 2018-11-06 23:39  溪水静幽  阅读(324)  评论(0)    收藏  举报