zoukankan      html  css  js  c++  java
  • @Valid springMVC bean校验不起作用及如何统一处理校验

    SpringMVC 使用JSR-303进行校验 @Valid

    使用注解

    一、准备校验时使用的JAR

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

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

    log4j、slf4j、slf4j-log4j

            <dependency>
                <groupId>javax.validation</groupId>
                <artifactId>validation-api</artifactId>
                <version>1.1.0.Final</version>
            </dependency>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>5.1.0.Final</version>
            </dependency>
            <dependency>
                <groupId>javax.el</groupId>
                <artifactId>el-api</artifactId>
                <version>2.2</version>
            </dependency>

     http://hibernate.org/validator/documentation/getting-started/

    	... 128 common frames omitted
    Caused by: javax.validation.ValidationException: HV000183: Unable to load 'javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath
    	at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<init>(ResourceBundleMessageInterpolator.java:172) ~[hibernate-validator-5.1.0.Final.jar:5.1.0.Final]
    	at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<init>(ResourceBundleMessageInterpolator.java:118) ~[hibernate-validator-5.1.0.Final.jar:5.1.0.Final]
    	at org.hibernate.validator.internal.engine.ConfigurationImpl.<init>(ConfigurationImpl.java:110) ~[hibernate-validator-5.1.0.Final.jar:5.1.0.Final]
    	at org.hibernate.validator.internal.engine.ConfigurationImpl.<init>(ConfigurationImpl.java:86) ~[hibernate-validator-5.1.0.Final.jar:5.1.0.Final]
    	at org.hibernate.validator.HibernateValidator.createGenericConfiguration(HibernateValidator.java:41) ~[hibernate-validator-5.1.0.Final.jar:5.1.0.Final]
    	at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:276) ~[validation-api-1.1.0.Final.jar:na]
    	... 137 common frames omitted

    http://www.tuicool.com/articles/eQf2Ejv

    http://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/http-entity/

    二、编写需要校验的bean

    @NotNull(message="名字不能为空")
    private String userName;
    @Max(value=120,message="年龄最大不能查过120")
    private int age;
    @Email(message="邮箱格式错误")
    private String email;

    三、校验方法

    复制代码
    @RequestMapping("/login")
        public String testValid(@Valid User user, BindingResult result){
            if (result.hasErrors()){
                List<ObjectError> errorList = result.getAllErrors();
                for(ObjectError error : errorList){
                    System.out.println(error.getDefaultMessage());
                }
            }
               
            return "test";
        }
    复制代码

    备注:这里一个@Valid的参数后必须紧挨着一个BindingResult 参数,否则spring会在校验不通过时直接抛出异常

    前台可以使用spring的标签库也可以自己自定义处理

    spring标签库的用法:

    复制代码
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>   
      
    <html>   
    <head>   
    <title>Reservation Form</title>   
    <style>   
    .error {   
        color: #ff0000;   
        font-weight: bold;   
    }   
    </style>   
    </head>   
      
    <body>   
        <form:form method="post" modelAttribute="vm">   
            <form:errors path="*" cssClass="error" />   
            <table>   
                <tr>   
                    <td>Name</td>   
                    <td><form:input path="userName" />   
                    </td>   
                    <td><form:errors path="userName" cssClass="error" />   
                    </td>   
                </tr>   
                <tr>   
                    <td>email</td>   
                    <td><form:input path="email" />   
                    </td>   
                    <td><form:errors path="email" cssClass="error" />   
                    </td>   
                </tr>   
           
                <tr>   
                    <td colspan="3"><input type="submit" />   
                    </td>   
                </tr>   
            </table>   
        </form:form>   
    </body>   
    </html> 
    复制代码

    四、开启spring的Valid功能

    <mvc:annotation-driven />

    五、JSR303定义的校验类型

    复制代码

    空检查

    @Null 验证对象是否为null

    @NotNull 验证对象是否不为null, 无法查检长度为0的字符串

    @NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格.

    @NotEmpty 检查约束元素是否为NULL或者是EMPTY.

    Booelan检查

    @AssertTrue 验证 Boolean 对象是否为 true

    @AssertFalse 验证 Boolean 对象是否为 false

    长度检查

    @Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内

    @Length(min=, max=) Validates that the annotated string is between min and max included.

    日期检查

    @Past 验证 Date 和 Calendar 对象是否在当前时间之前

    @Future 验证 Date 和 Calendar 对象是否在当前时间之后

    @Pattern 验证 String 对象是否符合正则表达式的规则

    数值检查,建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为"",Integer为null

    @Min 验证 Number 和 String 对象是否大等于指定的值

    @Max 验证 Number 和 String 对象是否小等于指定的值

    @DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度

    @DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度

    @Digits 验证 Number 和 String 的构成是否合法

    @Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。

    @Range(min=, max=) Checks whether the annotated value lies between (inclusive) the specified minimum and maximum.

    @Range(min=10000,max=50000,message="range.bean.wage")
    private BigDecimal wage;

    @Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证)

    @CreditCardNumber信用卡验证

    @Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。

    @ScriptAssert(lang= ,script=, alias=)

    @URL(protocol=,host=, port=,regexp=, flags=)

    复制代码

    6、自定义校验类型

    可以参考:http://exceptioneye.iteye.com/blog/1305040

    使用接口

    可以参考:http://elf8848.iteye.com/blog/1299587

    http://www.cnblogs.com/yangzhilong/p/3724967.html

     
        @RequestMapping("/add2")
        public String addStudentValid(@Valid @ModelAttribute("s") Student s,BindingResult result){
            if(result.hasErrors()){
                List<FieldError> fieldErrors = result.getFieldErrors();
                
                for (FieldError fieldError : fieldErrors) {
                    log.info("errors --"+fieldError.getField()+fieldError.getDefaultMessage());
                }
            }
            log.info("s.name="+s.getName());
            log.info("s.age="+s.getAge());
            return "success";
        }
    复制代码
    复制代码
    import javax.validation.constraints.Min;
    import org.hibernate.validator.constraints.Length;
    import org.hibernate.validator.constraints.NotEmpty;
    
    public class Student {
    
        @NotEmpty
        @Length(min=4,message="{stu.name}")
        private String name;
        @Min(value=18,message="{stu.age}")
        private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        
        @Override
        public String toString() {
            return "toString  -  name="+name+";age="+age;
        }
        
    }
    复制代码

    需要开启注解 <mvc:annotation-driven/>才能启用验证。否则@valid不管用。

    如果要使用错误提示的国际化消息,如stu.name为properties文件中的键值对
    @Length(min=4,message="{stu.name}")

    则需要在dispatcher-servlet.xml中配置

    复制代码
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">  
                <property name="basename" value="classpath:validmessages"/> 
                <property name="fileEncodings" value="utf-8"/>  
                <property name="cacheSeconds" value="120"/>  
    </bean>   
        
        <!-- 以下 validator  ConversionService 在使用 mvc:annotation-driven 会 自动注册-->  
        <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
            <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
            <!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties -->
            <property name="validationMessageSource" ref="messageSource" />
        </bean> 
        
        <mvc:annotation-driven validator="validator"/>
    复制代码


    在src/main/resources下放入validmessages.properties即可。

    上面的配置设置了自定义validator,使用messageSource为错误消息提示资源文件。

    validmessages.properties内容为

    stu.name=u540Du79F0u7684u957Fu5EA6u4E0Du80FDu5C0Fu4E8E{min}u554A!
    stu.age=u5E74u9F84u5FC5u987Bu5927u4E8E{value}u5C81u554A!

    可以通过{value} {min} {max}等引用注解里的值。

    当名称长度小于4 age小于18 输出:

    名称的长度不能小于4啊!
    age年龄必须大于18岁啊!

    本次测试的dispatcher-servlet.xml为

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>  
    <beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
     xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="  
        http://www.springframework.org/schema/beans   
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
        http://www.springframework.org/schema/context  
        http://www.springframework.org/schema/context/spring-context-3.0.xsd  
        http://www.springframework.org/schema/mvc  
        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd  
         http://www.springframework.org/schema/tx
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        ">  
       
       
       <context:component-scan base-package="com.upper"/>
       
        <!-- freemarker的配置 -->  
        <bean id="freemarkerConfigurer"  
            class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">  
            <property name="templateLoaderPath" value="/WEB-INF/views/" />  
            <property name="defaultEncoding" value="GBK" />  
            <property name="freemarkerSettings">  
                <props>  
                    <prop key="template_update_delay">0</prop>  
                    <prop key="locale">zh_CN</prop>  
                    <prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop>  
                    <prop key="date_format">yyyy-MM-dd</prop>  
                    <prop key="number_format">#.##</prop>  
                    <!--  <prop key="auto_import">c_index.tpl as p</prop> -->
                </props>  
            </property>  
        </bean>  
        <!-- FreeMarker视图解析 如返回userinfo。。在这里配置后缀名ftl和视图解析器。。 -->  
        <bean id="viewResolver"  
            class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">  
            <property name="viewClass"  
                value="org.springframework.web.servlet.view.freemarker.FreeMarkerView" />  
            <property name="suffix" value=".ftl" />  
            <property name="contentType" value="text/html;charset=GBK" />  
            <property name="exposeRequestAttributes" value="true" />  
            <property name="exposeSessionAttributes" value="true" />  
            <property name="exposeSpringMacroHelpers" value="true" />  
            <property name="requestContextAttribute" value="rc" />  
            <property name="allowSessionOverride" value="true"/>  
        </bean> 
        
        
        <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">  
                <property name="basename" value="classpath:validmessages"/>  
                <property name="fileEncodings" value="utf-8"/>  
                <property name="cacheSeconds" value="120"/>  
        </bean>   
        
        <!-- 以下 validator  ConversionService 在使用 mvc:annotation-driven 会 自动注册-->  
        <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
            <!-- 如果不加默认到 使用classpath下的 ValidationMessages.properties -->
            <property name="validationMessageSource" ref="messageSource" />
        </bean> 
        
        <mvc:annotation-driven validator="validator"/>
    </beans>

    http://www.cnblogs.com/beenupper/p/3395872.html

    对于后端的参数校验,我们一直在强调的验证规则,提示信息的重用。这不,springmvc通过集成Valid最大程序减少了我们的工作量。其实后端的参数过滤,是分几种请求来源的。每种的处理都不太一样,但是我们如果能重用验证规则,提示信息,那就很强大了。
    1 常用的表单提交,需要页面返回错误信息
    2 AJAX提交,需要JSON格式返回,或者XML
    3 接口调用,同样需要对应的数据格式返回
    对于这3类请求,我今天讲的是第3种,是可以重用第1种的资源和验证规则。
    考虑通过AOP加注解,拦截方法中的BEAN,通过获取期验证返回信息,提前抛出验证异常。
     

    里面的processValidationError方法会处理具体异常的返回值并以JSON输出,大功告成.
    整体代码链接。
    demo代码:https://github.com/igool/validatedemo
    子模块:https://github.com/igool/lombakcode

    当这样处理之后,我们的resetful的接口只用处理真正的业务,完全不用做常用的参数检查。

    http://www.blogjava.net/zuxiong/archive/2015/11/27/428389.html

  • 相关阅读:
    CentOS6 配置阿里云 NTP 服务
    使用docker-compose运行nginx容器挂载时遇到的文件/目录问题
    Springboot配置文件参数使用docker-compose实现动态配置
    Dockerfile文件全面详解
    docker 生成mysql镜像启动时自动执行sql
    CentOS无法识别NTFS格式U盘完美解决方案
    网络模型与网络策略
    k8s更换网络插件:从flannel更换成calico
    数据采集实战(四)-- 线性代数习题答案下载
    leedcode 146. LRU 缓存机制(哈希+双向链表)
  • 原文地址:https://www.cnblogs.com/softidea/p/5839327.html
Copyright © 2011-2022 走看看