@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=\u540D\u79F0\u7684\u957F\u5EA6\u4E0D\u80FD\u5C0F\u4E8E{min}\u554A!
stu.age=\u5E74\u9F84\u5FC5\u987B\u5927\u4E8E{value}\u5C81\u554A!

 

可以通過{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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM