zoukankan      html  css  js  c++  java
  • SpringMVC 使用JSR-303进行校验 @Valid

    注意:1 public String save(@ModelAttribute("house") @Valid House entity, BindingResult result,HttpServletRequest request,  Model model)     BindingResult 必须放在model,request前面

       2 validation-api-1.0.0.GA.jar是JDK的接口;hibernate-validator-4.2.0.Final.jar是对上述接口的实现。hibernate-validator-4.2.0.Final可以,但是hibernate-validator-4.3.0.Final报错

    验证注解

    验证的数据类型

    说明

    @AssertFalse

    Boolean,boolean

    验证注解的元素值是false

    @AssertTrue

    Boolean,boolean

    验证注解的元素值是true

    @NotNull

    任意类型

    验证注解的元素值不是null

    @Null

    任意类型

    验证注解的元素值是null

    @Min(value=值)

    BigDecimal,BigInteger, byte,

    short, int, long,等任何Number或CharSequence(存储的是数字)子类型

    验证注解的元素值大于等于@Min指定的value值

    @Max(value=值)

    和@Min要求一样

    验证注解的元素值小于等于@Max指定的value值

    @DecimalMin(value=值)

    和@Min要求一样

    验证注解的元素值大于等于@ DecimalMin指定的value值

    @DecimalMax(value=值)

    和@Min要求一样

    验证注解的元素值小于等于@ DecimalMax指定的value值

    @Digits(integer=整数位数, fraction=小数位数)

    和@Min要求一样

    验证注解的元素值的整数位数和小数位数上限

    @Size(min=下限, max=上限)

    字符串、Collection、Map、数组等

    验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小

    @Past

    java.util.Date,

    java.util.Calendar;

    Joda Time类库的日期类型

    验证注解的元素值(日期类型)比当前时间早

    @Future

    与@Past要求一样

    验证注解的元素值(日期类型)比当前时间晚

    @NotBlank

    CharSequence子类型

    验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的首位空格

    @Length(min=下限, max=上限)

    CharSequence子类型

    验证注解的元素值长度在min和max区间内

    @NotEmpty

    CharSequence子类型、Collection、Map、数组

    验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)

    @Range(min=最小值, max=最大值)

    BigDecimal,BigInteger,CharSequence, byte, short, int, long等原子类型和包装类型

    验证注解的元素值在最小值和最大值之间

    @Email(regexp=正则表达式,

    flag=标志的模式)

    CharSequence子类型(如String)

    验证注解的元素值是Email,也可以通过regexp和flag指定自定义的email格式

    @Pattern(regexp=正则表达式,

    flag=标志的模式)

    String,任何CharSequence的子类型

    验证注解的元素值与指定的正则表达式匹配

    @Valid

    任何非原子类型

    指定递归验证关联的对象;

    如用户对象中有个地址对象属性,如果想在验证用户对象时一起验证地址对象的话,在地址对象上加@Valid注解即可级联验证

     

    一、准备校验时使用的JAR

          

      说明:

             validation-api-1.0.0.GA.jar是JDK的接口;

             hibernate-validator-4.2.0.Final.jar是对上述接口的实现。

    ------------------------------------------------------------------------------------------------

    新增一个测试的pojo bean ,增加jsr 303格式的验证annotation

    Java代码 复制代码  收藏代码
    Java代码  收藏代码
    1. @NotEmpty  
    2. private String userName;  
    3. @Email  
    4. private String email;  


    在controller 类中的handler method中,对需要验证的对象前增加@Valid 标志

    Java代码 复制代码  收藏代码
    Java代码  收藏代码
    1. @RequestMapping("/valid")  
    2. public String valid(@ModelAttribute("vm") [color=red]@Valid[/color] ValidModel vm, BindingResult result) {  
    3.     if (result.hasErrors()) {  
    4.         return "validResult";  
    5.     }  
    6.   
    7.     return "helloworld";  
    8. }  


    增加显示验证结果的jsp如下

    Jsp代码 复制代码  收藏代码
    Jsp代码  收藏代码
    1. <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>  
    2.   
    3. <html>  
    4. <head>  
    5. <title>Reservation Form</title>  
    6. <style>  
    7. .error {  
    8.     color: #ff0000;  
    9.     font-weight: bold;  
    10. }  
    11. </style>  
    12. </head>  
    13.   
    14. <body>  
    15.     <form:form method="post" modelAttribute="vm">  
    16.         <form:errors path="*" cssClass="error" />  
    17.         <table>  
    18.             <tr>  
    19.                 <td>Name</td>  
    20.                 <td><form:input path="userName" />  
    21.                 </td>  
    22.                 <td><form:errors path="userName" cssClass="error" />  
    23.                 </td>  
    24.             </tr>  
    25.             <tr>  
    26.                 <td>email</td>  
    27.                 <td><form:input path="email" />  
    28.                 </td>  
    29.                 <td><form:errors path="email" cssClass="error" />  
    30.                 </td>  
    31.             </tr>  
    32.       
    33.             <tr>  
    34.                 <td colspan="3"><input type="submit" />  
    35.                 </td>  
    36.             </tr>  
    37.         </table>  
    38.     </form:form>  
    39. </body>  
    40. </html>  


    访问 http://localhost:8080/springmvc/valid?userName=winzip&email=winzip 
    查看验证结果。 
    二:自定义jsr 303格式的annotation 
    参考hibernate validator 4 reference 手册中3.1节,增加一个自定义要求输入内容为定长的annotation验证类 
    新增annotation类定义

    Java代码 复制代码  收藏代码
    Java代码  收藏代码
    1. @Target( { METHOD, FIELD, ANNOTATION_TYPE })  
    2. @Retention(RUNTIME)  
    3. @Constraint(validatedBy = FixLengthImpl.class)  
    4. public @interface FixLength {  
    5.   
    6.     int length();  
    7.     String message() default "{net.zhepu.web.valid.fixlength.message}";  
    8.   
    9.     Class<?>[] groups() default {};  
    10.   
    11.     Class<? extends Payload>[] payload() default {};  
    12. }  


    及具体的验证实现类如下

    Java代码 复制代码  收藏代码
    Java代码  收藏代码
    1. public class FixLengthImpl implements ConstraintValidator<FixLength, String> {  
    2.     private int length;  
    3.     @Override  
    4.     public boolean isValid(String validStr,  
    5.             ConstraintValidatorContext constraintContext) {  
    6.         if (validStr.length() != length) {  
    7.             return false;  
    8.         } else {  
    9.             return true;  
    10.         }  
    11.     }  
    12.   
    13.     @Override  
    14.     public void initialize(FixLength fixLen) {  
    15.         this.length = fixLen.length();  
    16.     }  
    17. }  


    为使自定义验证标注的message正常显示,需要修改servlet context配置文件,新增messageSource bean,如下

    Xml代码 复制代码  收藏代码
    1.   
    Xml代码  收藏代码
    1. <bean id="messageSource"  
    2.     class="org.springframework.context.support.ReloadableResourceBundleMessageSource"  
    3.     p:fallbackToSystemLocale="true" p:useCodeAsDefaultMessage="false"  
    4.     p:defaultEncoding="UTF-8">  
    5.     <description>Base message source to handle internationalization  
    6.     </description>  
    7.     <property name="basenames">  
    8.         <list>  
    9.             <!-- main resources -->  
    10.             <value>classpath:valid/validation</value>  
    11.         </list>  
    12.     </property>  
    13. </bean>  


    表示spring 将从路径valid/validation.properties中查找对于的message。 
    新增valid bean 引用新增的messageSource bean,表示valid message将从messageSource bean 注入。

    Xml代码 复制代码  收藏代码
    Xml代码  收藏代码
    1. <bean id="validator"  
    2.     class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"  
    3.     p:validationMessageSource-ref="messageSource">  
    4.     <description>Enable the bean validation provider, and configure it to  
    5.         use the messageSource when resolving properties</description>  
    6. </bean>  



    修改 <mvc:annotation-driven> 增加对validator bean的引用

    Xml代码 复制代码  收藏代码
    Xml代码  收藏代码
    1. <mvc:annotation-driven validator="validator" />  



    最后修改之前新增的pojo bean ,新增一个mobileNO属性并增加对自定义标注的引用

    Java代码 复制代码  收藏代码
    Java代码  收藏代码
    1. @FixLength(length=11)  
    2. private String mobileNO;  


    在前端jsp中也增加新字段的支持

    Jsp代码 复制代码  收藏代码
    Jsp代码  收藏代码
    1. <tr>  
    2.     <td>mobileno</td>  
    3.     <td><form:input path="mobileNO" />  
    4.     </td>  
    5.     <td><form:errors path="mobileNO" cssClass="error" />  
    6.     </td>  
    7. </tr>  



    可访问url http://localhost:8080/springmvc/valid?userName=winzip&email=winzip&mobileNO=138188888 
    来查看修改的结果。 

    三 json输入的验证 
    Spring mvc 3.0.5中对于json格式的输入直接使用@valid标注有问题,目前这个bug还未修复 (见 SPR-6709),预计在3.1 m2版本中会修复。 
    在此之前,可以通过如下几种方式来对json(或xml)格式的输入来进行验证。 
    1:在handler method中直接对输入结果进行验证

    Java代码 复制代码  收藏代码
    Java代码  收藏代码
    1. @RequestMapping("/validJson1")  
    2. @ResponseBody  
    3. public JsonResult processSubmitjson(@RequestBody ValidModel vm,  
    4.         HttpServletRequest request) {  
    5.     JsonResult jsonRst = new JsonResult();  
    6.       
    7.     Set<ConstraintViolation<ValidModel>> set = validator.validate(vm);  
    8.     for (ConstraintViolation<ValidModel> violation : set) {  
    9.   
    10.         String propertyPath = violation.getPropertyPath().toString();  
    11.         ;  
    12.         String message = violation.getMessage();  
    13.         log.error("invalid value for: '" + propertyPath + "': "  
    14.                 + message);  
    15.     }         
    16.     if (!set.isEmpty()){  
    17.         jsonRst.setSuccess(false);  
    18.         jsonRst.setMsg("输入有误!");  
    19.         return jsonRst;  
    20.     }  
    21.   
    22.     jsonRst.setSuccess(true);  
    23.     jsonRst.setMsg("输入成功!");  
    24.     return jsonRst;  
    25. }  




    可通过修改后的helloworld.jsp中的json valid test1按钮进行调用测试。 

    2:将此验证逻辑封装为一个AOP,当需验证的对象前有@valid标注和@RequestBody标注时开始验证 
    新增handler method如下

    Java代码 复制代码  收藏代码
    Java代码  收藏代码
    1. @RequestMapping("/validJson2")  
    2.  @ResponseBody  
    3.  public JsonResult testJson4(@RequestBody @Valid ValidModel vm){  
    4.     log.info("handle json for valid");  
    5.     return new JsonResult(true,"return ok");      
    6.  }  


    这里没有对输入值做任何验证,所有的验证都在AOP中完成。 
    修改pom.xml增加对AOP相关类库的引用。

    Xml代码 复制代码  收藏代码
    Xml代码  收藏代码
    1. <dependency>  
    2.     <groupId>org.aspectj</groupId>  
    3.     <artifactId>aspectjweaver</artifactId>  
    4.     <version>1.6.11</version>  
    5. </dependency>  
    6.   
    7. <dependency>  
    8.     <groupId>cglib</groupId>  
    9.     <artifactId>cglib</artifactId>  
    10.     <version>2.2.2</version>  
    11. </dependency>  
    12.   
    13. <dependency>  
    14.     <groupId>org.springframework</groupId>  
    15.     <artifactId>spring-aop</artifactId>  
    16.     <version>${org.springframework.version}</version>  
    17. </dependency>  


    修改servet context xml,增加对aop的支持。

    Xml代码 复制代码  收藏代码
    Xml代码  收藏代码
    1. <!-- enable Spring AOP support -->  
    2. <aop:aspectj-autoproxy proxy-target-class="true" />  


    最后,新增AOP类

    Java代码 复制代码  收藏代码
    Java代码  收藏代码
    1. public class CustomerValidatorAOP {  
    2.   private Validator validator;  
    3.    
    4.   @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")  
    5.   private void controllerInvocation() {  
    6.   }  
    7.    
    8.   @Around("controllerInvocation()")  
    9.   public Object aroundController(ProceedingJoinPoint joinPoint) throws Throwable {  
    10.    
    11.     MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();  
    12.     Method method = methodSignature.getMethod();  
    13.     Annotation[] annotationList = method.getAnnotations();  
    14.    /* for(Annotation anno:annotationList){ 
    15.         System.out.println(ResponseBody.class.isInstance(anno)); 
    16.     } 
    17. */  
    18.     Annotation[][] argAnnotations = method.getParameterAnnotations();  
    19.     String[] argNames = methodSignature.getParameterNames();  
    20.     Object[] args = joinPoint.getArgs();  
    21.    
    22.     for (int i = 0; i < args.length; i++) {  
    23.       if (hasRequestBodyAndValidAnnotations(argAnnotations[i])) {  
    24.         Object ret = validateArg(args[i], argNames[i]);  
    25.         if(ret != null){  
    26.             return ret;  
    27.         }  
    28.       }  
    29.     }  
    30.    
    31.     return joinPoint.proceed(args);  
    32.   }  
    33.    
    34.   private boolean hasRequestBodyAndValidAnnotations(Annotation[] annotations) {  
    35.     if (annotations.length < 2)  
    36.       return false;  
    37.    
    38.     boolean hasValid = false;  
    39.     boolean hasRequestBody = false;  
    40.    
    41.     for (Annotation annotation : annotations) {  
    42.       if (Valid.class.isInstance(annotation))  
    43.         hasValid = true;  
    44.       else if (RequestBody.class.isInstance(annotation))  
    45.         hasRequestBody = true;  
    46.    
    47.       if (hasValid && hasRequestBody)  
    48.         return true;  
    49.     }  
    50.     return false;  
    51.   }  
    52.    
    53.   
    54.   private JsonResult validateArg(Object arg, String argName) {  
    55.     BindingResult result = getBindingResult(arg, argName);  
    56.     validator.validate(arg, result);  
    57.     if (result.hasErrors()) {  
    58.       JsonResult jsonresult = new JsonResult();  
    59.       jsonresult.setSuccess(false);  
    60.       jsonresult.setMsg("fail");  
    61.       return jsonresult;  
    62.     }  
    63.     return null;  
    64.   }  
    65.    
    66.   private BindingResult getBindingResult(Object target, String targetName) {  
    67.     return new BeanPropertyBindingResult(target, targetName);  
    68.   }  
    69.    
    70.   @Required  
    71.   public void setValidator(Validator validator) {  
    72.     this.validator = validator;  
    73.   }  


    这里只考虑了输入为json格式的情况,仅仅作为一种思路供参考,实际使用时需要根据项目具体情况进行调整。 
    可通过修改后的helloworld.jsp中的json valid test2按钮进行调用测试。

    原文:http://starscream.iteye.com/blog/1068905

     

  • 相关阅读:
    我的知识库(4) java获取页面编码(Z)
    知识库(3)JAVA 正则表达式 (超详细)
    The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the associated filter. Struts
    某人总结的《英语听力的技巧 》,挺搞的
    我的知识库(5)java单例模式详解
    构建可扩展程序
    SerialPort (RS232 Serial COM Port) in C# .NET
    Python学习笔记——String、Sequences
    UI题目我的答案
    jQuery学习系列学会操纵Form表单元素(1)
  • 原文地址:https://www.cnblogs.com/eggbucket/p/3264074.html
Copyright © 2011-2022 走看看