Hibernator-Validator

1.maven
SpringBoot starter-web自動引入其依賴,因為web模塊默認使用了hibernate-validator

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2.model校驗
對郵箱進行檢測注盈,message用作校驗失敗時的提示信息匙奴。

public class User {
    private Long id;
    private String name;
    private Integer age;
    @Email(message = "郵箱格式錯誤")
    private String email;
    ..
    ..
}

3.在controller(Rest層)添加校驗
參數(shù)前需要加上@Validated注解魄健,表明需要spring對其進行校驗,而校驗的信息會存放到其后的BindingResult中殖告。

@RequestMapping(value = "/addUser", method = RequestMethod.PUT)
    @ResponseBody
    public String addUser(@RequestBody @Validated User user) {
        User u = new User();
        u.setName(user.getName());
        u.setAge(user.getAge());
        userMapper.insert(u);
        return "success";
    }

4.異常捕捉
你可以直接在方法里捕捉反饋驗證錯誤信息


而我是用了全局統(tǒng)一異常的處理

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class MyExceptionHandle {
    private static final Logger logger = LoggerFactory.getLogger(MyExceptionHandle.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public String handle(Exception e) {

        if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex=(MethodArgumentNotValidException)e;
            BindingResult bindingResult = ex.getBindingResult();
            StringBuffer stringBuffer = new StringBuffer();
            if(bindingResult.hasErrors()){
                for (FieldError fieldError : bindingResult.getFieldErrors()) {
                    //該格式僅僅作為response展示和log作用阿蝶,前端應(yīng)自己做校驗
                    stringBuffer.append(fieldError.getObjectName() + "--" +fieldError.getDefaultMessage() + " ");
                }
            }
            logger.error(stringBuffer.toString());
            return HttpStatus.BAD_REQUEST.value()+stringBuffer.toString();
        }
        e.printStackTrace(); // 打印異常棧
        return e.getMessage();
    }

}




測試
因為我用了swagger-ui,所以直接在這里面測試黄绩,你們可以訪問URL測試

HttpStatus.BAD_REQUEST.value()是檢測變量名羡洁,getFieldErrors()是一個List。

注意:參數(shù)前需要加上@Validated注解爽丹,表明需要spring對其進行校驗筑煮,而校驗的信息會存放到其后的BindingResult中。注意粤蝎,必須相鄰真仲,如果有多個參數(shù)需要校驗,形式可以如下初澎。foo(@Validated Foo foo, BindingResult fooBindingResult 秸应,@Validated Bar bar, BindingResult barBindingResult);即一個校驗類對應(yīng)一個校驗結(jié)果。

6.分組校驗
當我們遇到不同場景需要有不同的校驗規(guī)則時候碑宴,我們可以使用分組校驗软啼。如:一個請求只校驗id,一個請求只校驗email:
新建兩個分組(Name,Email)接口

public interface Name{
}

public interface Email{
}

修改實體類

public class User {
    private Long id;
    @Length(min = 2,message = "名字至少2位",groups = {Name.class})
    private String name;
    private Integer age;
    @Email(message = "郵箱格式錯誤",,groups = {Email.class})
    private String email;
    ..
    ..
}

@Validated屬性中指定需要校驗的分組名,可以指定1到多個,@Validated({a.class,b.class,...}) 延柠。指定到的分組名會全部進行校驗祸挪,不指定的不校驗,這里我們就只對Name組的驗證,而忽略其他的(Email)

    @ResponseBody
    public String addUser(@RequestBody @Validated({Name.class})  User user) {
        User u = new User();
        u.setName(user.getName());
        u.setAge(user.getAge());
        userMapper.insert(u);
        return "success";
    }

測試


7.對象級聯(lián)校驗
對象內(nèi)部包含另一個對象作為屬性贞间,屬性上加@Valid(不可以用@Validated贿条,參考10)雹仿,可以驗證作為屬性的對象內(nèi)部的驗證,來實現(xiàn)嵌套驗證整以。
現(xiàn)在有個實體叫做Item:

public class Item {

    @NotNull(message = "id不能為空")
    @Min(value = 1, message = "id必須為正整數(shù)")
    private Long id;

    @NotNull(message = "props不能為空")
    @Size(min = 1, message = "至少要有一個屬性")
    private List<Prop> props;
}

屬性這個實體也有自己的驗證機制胧辽,比如屬性和屬性值id不能為空,屬性名和屬性值不能為空等悄蕾。

public class Prop {

    @NotNull(message = "pid不能為空")
    @Min(value = 1, message = "pid必須為正整數(shù)")
    private Long pid;

    @NotNull(message = "vid不能為空")
    @Min(value = 1, message = "vid必須為正整數(shù)")
    private Long vid;

    @NotBlank(message = "pidName不能為空")
    private String pidName;

    @NotBlank(message = "vidName不能為空")
    private String vidName;
}

現(xiàn)在我們有個 ItemController 接受一個Item的入?yún)⑵惫耍胍獙tem進行驗證础浮,如下所示:

@RestController
public class ItemController {

    @RequestMapping("/item/add")
    public void addItem(@Validated Item item, BindingResult bindingResult) {
        doSomething();
    }
}

如果Item實體的props屬性不額外加注釋帆调,只有@NotNull和@Size,無論入?yún)⒉捎聾Validated還是@Valid驗證豆同,Spring Validation框架只會對Item的id和vid等屬性做非空和數(shù)量驗證番刊,不會對props字段里的Prop實體進行字段驗證,也就是@Validated和@Valid加在方法參數(shù)前影锈,都不會自動對參數(shù)進行嵌套驗證芹务。也就是說如果傳的List中有Prop的pid為空或者是負數(shù),入?yún)Ⅱ炞C不會檢測出來鸭廷。

為了能夠進行嵌套驗證枣抱,必須手動在Item實體的props字段上明確指出這個字段里面的實體也要進行驗證。由于@Validated不能用在成員屬性(字段)上辆床,但是@Valid能加在成員屬性(字段)上佳晶,而且@Valid類注解上也說明了它支持嵌套驗證功能,那么我們能夠推斷出:@Valid加在方法參數(shù)時并不能夠自動進行嵌套驗證讼载,而是用在需要嵌套驗證類的相應(yīng)字段上轿秧,來配合方法參數(shù)上@Validated或@Valid來進行嵌套驗證。
我們修改Item類如下所示:

public class Item {

    @NotNull(message = "id不能為空")
    @Min(value = 1, message = "id必須為正整數(shù)")
    private Long id;

    @Valid // 嵌套驗證必須用@Valid
    @NotNull(message = "props不能為空")
    @Size(min = 1, message = "props至少要有一個自定義屬性")
    private List<Prop> props;
}

然后我們在ItemController的addItem函數(shù)上再使用@Validated或者@Valid咨堤,就能對Item的入?yún)⑦M行嵌套驗證菇篡。此時Item里面的props如果含有Prop的相應(yīng)字段為空的情況,Spring Validation框架就會檢測出來一喘,bindingResult就會記錄相應(yīng)的錯誤驱还。

8.GET參數(shù)校驗(@RequestParam參數(shù)校驗)
a.此時需要使用MethodValidationPostProcessor 的Bean
暫時不深究

b.方法所在的Controller上加注解@Validated

@RequestMapping("/validation")
@RestController
@Validated
public class ValidationController {
    /**如果只有少數(shù)對象,直接把參數(shù)寫到Controller層凸克,然后在Controller層進行驗證就可以了议蟆。*/
    @RequestMapping(value = "/demo3", method = RequestMethod.GET)
    public void demo3(@Range(min = 1, max = 9, message = "年級只能從1-9")
                      @RequestParam(name = "grade", required = true)
                      int grade,
                      @Min(value = 1, message = "班級最小只能1")
                      @Max(value = 99, message = "班級最大只能99")
                      @RequestParam(name = "classroom", required = true)
                      int classroom) {
        System.out.println(grade + "," + classroom);
    }
}

9.hibernate的校驗?zāi)J?/strong>
1、普通模式(默認是這個模式)
  普通模式(會校驗完所有的屬性触徐,然后返回所有的驗證失敗信息)咪鲜。但是在使用組序列驗證的時候,如果序列前邊的組驗證失敗撞鹉,則后面的組將不再給予驗證疟丙。

2颖侄、快速失敗返回模式
  快速失敗返回模式(只要有一個驗證失敗,則返回)

3.如果需要配置為快速失敗返回享郊,則編寫配置文件
(hibernate.validator.fail_fast:true 快速失敗返回模式 false 普通模式)

@Configuration
public class ValidatorConfiguration {
    @Bean
    public Validator validator(){
        ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
                .configure()
                .addProperty( "hibernate.validator.fail_fast", "true" )
                .buildValidatorFactory();
        Validator validator = validatorFactory.getValidator();

        return validator;
    }
}

10.@Valid和@Validated的總結(jié)區(qū)分
Spring Validation驗證框架對參數(shù)的驗證機制提供了@Validated(Spring's JSR-303 規(guī)范览祖,是標準 JSR-303 的一個變種),javax提供了@Valid(標準JSR-303規(guī)范)炊琉,配合 BindingResult 可以直接提供參數(shù)驗證結(jié)果展蒂。@Validated是@Valid 的一次封裝,是Spring提供的校驗機制使用苔咪。在檢驗 Controller 的入?yún)⑹欠穹弦?guī)范時锰悼,使用 @Validated 或者 @Valid 在基本驗證功能上沒有太多區(qū)別。但是在分組团赏、注解地方箕般、嵌套驗證等功能上兩個有所不同:

  1. 分組
    @Validated:提供了一個分組功能,可以在入?yún)Ⅱ炞C時舔清,根據(jù)不同的分組采用不同的驗證機制丝里,這個網(wǎng)上也有資料,不詳述体谒。@Valid:作為標準JSR-303規(guī)范杯聚,還沒有吸收分組的功能。

  2. 注解地方

@Validated:可以用在類型抒痒、方法和方法參數(shù)上幌绍。但是不能用在成員屬性(字段)上
@Valid:可以用在方法、構(gòu)造函數(shù)评汰、方法參數(shù)和成員屬性(字段)上
兩者是否能用于成員屬性(字段)上直接影響能否提供嵌套驗證的功能纷捞。

所以可以搭配著用,我習慣是除嵌套驗證的屬性字段上用@Valid被去,其他都用@Validated主儡。



API

JSR提供的校驗注解

@Null   被注釋的元素必須為 null    
@NotNull    被注釋的元素必須不為 null    
@AssertTrue     被注釋的元素必須為 true    
@AssertFalse    被注釋的元素必須為 false    
@Min(value)     被注釋的元素必須是一個數(shù)字,其值必須大于等于指定的最小值    
@Max(value)     被注釋的元素必須是一個數(shù)字惨缆,其值必須小于等于指定的最大值    
@DecimalMin(value)  被注釋的元素必須是一個數(shù)字糜值,其值必須大于等于指定的最小值    
@DecimalMax(value)  被注釋的元素必須是一個數(shù)字,其值必須小于等于指定的最大值    
@Size(max=, min=)   被注釋的元素的大小必須在指定的范圍內(nèi)    
@Digits (integer, fraction)     被注釋的元素必須是一個數(shù)字坯墨,其值必須在可接受的范圍內(nèi)    
@Past   被注釋的元素必須是一個過去的日期    
@Future     被注釋的元素必須是一個將來的日期    
@Pattern(regex=,flag=)  被注釋的元素必須符合指定的正則表達式
-------------------------------------------------------------------------------------------------
Hibernate Validator提供的校驗注解

@NotBlank(message =)   驗證字符串非null寂汇,且長度必須大于0    
@Email  被注釋的元素必須是電子郵箱地址    
@Length(min=,max=)  被注釋的字符串的大小必須在指定的范圍內(nèi)    
@NotEmpty   被注釋的字符串的必須非空    
@Range(min=,max=,message=)  被注釋的元素必須在合適的范圍內(nèi)

參考文檔:
https://www.cnblogs.com/itrena/p/8833054.html(繁瑣但是詳細)
https://blog.csdn.net/qq_35703608/article/details/81304608(快速入手)

<--完-->

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市捣染,隨后出現(xiàn)的幾起案子骄瓣,更是在濱河造成了極大的恐慌,老刑警劉巖耍攘,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榕栏,死亡現(xiàn)場離奇詭異畔勤,居然都是意外死亡,警方通過查閱死者的電腦和手機扒磁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門庆揪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人妨托,你說我怎么就攤上這事缸榛。” “怎么了兰伤?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵内颗,是天一觀的道長。 經(jīng)常有香客問我医清,道長起暮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任会烙,我火速辦了婚禮,結(jié)果婚禮上筒捺,老公的妹妹穿的比我還像新娘柏腻。我一直安慰自己,他們只是感情好系吭,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布五嫂。 她就那樣靜靜地躺著,像睡著了一般肯尺。 火紅的嫁衣襯著肌膚如雪沃缘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天则吟,我揣著相機與錄音槐臀,去河邊找鬼。 笑死氓仲,一個胖子當著我的面吹牛水慨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播敬扛,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼晰洒,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了啥箭?” 一聲冷哼從身側(cè)響起谍珊,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎急侥,沒想到半個月后砌滞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炼七,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年布持,在試婚紗的時候發(fā)現(xiàn)自己被綠了豌拙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡题暖,死狀恐怖按傅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情胧卤,我是刑警寧澤唯绍,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站枝誊,受9級特大地震影響况芒,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叶撒,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一绝骚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧祠够,春花似錦压汪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至落君,卻和暖如春穿香,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背绎速。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工皮获, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人朝氓。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓魔市,卻偏偏與公主長得像,于是被迫代替她去往敵國和親赵哲。 傳聞我的和親對象是個殘疾皇子待德,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355