spring?boot?validation參數(shù)校驗(yàn)與分組嵌套各種類型及使用小結(jié)
寫在前面:
參數(shù)校驗(yàn)基本上是controller必做的事情,畢竟前端傳過來(lái)的一切都不可信。 但是每次if(StrUtil.isNotNull())啥的有時(shí)候多還難寫。validation可以簡(jiǎn)化這一操作。
項(xiàng)目構(gòu)建
采用boot3,主要依賴為spring web 和validation

主要依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
項(xiàng)目結(jié)構(gòu)

問題展示
先來(lái)個(gè)簡(jiǎn)單的案例
@RestController
public class ValidationController {
@GetMapping("/get")
public String get(String name,String age){
System.out.println(name);
System.out.println(age);
return "ok";
}
}
點(diǎn)擊這個(gè)就可以發(fā)送請(qǐng)求了

發(fā)送出去不會(huì)做任何校驗(yàn)

這個(gè)的處理我們可以選擇加上@RequestParam注解。@RequestParam默認(rèn)屬性require為true,就是必須要傳值,
public String get(@RequestParam String name,@RequestParam String age)
報(bào)錯(cuò)返回

封裝成實(shí)體類也是一樣的。
但是這樣只能做非null判斷,不能做復(fù)雜的判斷。在body里面的時(shí)候更加不會(huì)校驗(yàn)了

validation使用
那么validation又如何做到呢。
快速入門
需求:get請(qǐng)求中,name長(zhǎng)度在2-10,age在10-100歲之間且都不為null。
@GetMapping("/get")
public String get(@Length(max = 10,min = 2) String name,
@Min(10)@Max(100) String age){
System.out.println("name = " + name);
System.out.println("age = " + age);
return "ok";
}
為null發(fā)送,好ok一點(diǎn)用沒有。

我查資料發(fā)現(xiàn)需要參數(shù)前面加上啟動(dòng)校驗(yàn)@Validated或者@Valid注解,但是無(wú)論我怎么放到都是沒有校驗(yàn)。全部無(wú)效。

我之前研究了半天,然后才發(fā)現(xiàn),如果想要這樣校驗(yàn)的話,需要在controller類上面加上@Validated且Valid都不行。

如果是實(shí)體類接收就不一樣了。直接在方法就可以了

注釋
到這里基本使用應(yīng)該就差不多知道了?,F(xiàn)在來(lái)進(jìn)行注解的學(xué)習(xí)。
注解通用屬性基本上都有的
| 屬性 | 描述 |
|---|---|
| message | 錯(cuò)誤返回描述 |
| groups | 分組,可以進(jìn)行更加靈活的選擇。 |
| payload |
無(wú)參注解,無(wú)必須傳的值
| 注解 | 限制 | 類型 |
|---|---|---|
| @Null | 限制只能為null | 接收任何類型,這個(gè)應(yīng)該用的比較少 |
| @NotNull | 限制必須不為null | 接收任何類型 |
| @AssertFalse | 限制必須為false | 支持的類型包括 boolean 和 Boolean。null 元素被視為有效。 |
| @AssertTrue | 限制必須為true | 支持的類型包括 boolean 和 Boolean。null 元素被視為有效。 |
| @Future | 限制必須是一個(gè)將來(lái)的日期 | 大部分的時(shí)間類如果Date、Calendar、Instant、LocalDate等。null 元素被視為有效 |
| @Past | 限制必須是過去的時(shí)刻、日期或時(shí)間 | 和上面一樣 |
| @PastOrPresent | 帶注釋的元素必須是過去或現(xiàn)在的時(shí)刻、日期或時(shí)間 | 同上 |
| @NotEmpty | 帶批注的元素不得為 null和空 | CharSequence(計(jì)算字符序列的長(zhǎng)度)Collection (集合大?。㎝ap (大小)數(shù)組(計(jì)算數(shù)組長(zhǎng)度) |
| @NotBlank | 帶批注的元素不得且 null 必須至少包含一個(gè)非空格字符 | CharSequence |
| @Positive | 帶注釋的元素必須是嚴(yán)格的正數(shù)(即 0 被視為無(wú)效值)。 | BigDecimal、BigInteger、byteintlong、 short及其floatdouble各自的包裝器 |
| @PositiveOrZero | 正數(shù)或0 | 同上 |
大小注解,用于限值大小
| 注解 | 限制 | 類型 |
|---|---|---|
| @DecimalMax(value,inclusive) | 限制必須為一個(gè)不大于指定值的value數(shù)字,inclusive:指定指定的最小值是包含的還是排除的true為不包括最小值 | BigDecimal、BigInteger、CharSequence、byte、 shortintlong及其各自的包裝器,請(qǐng)注意, double 由于舍入錯(cuò)誤,不支持 (某些 float 提供程序可能會(huì)提供一些近似支持)。null 元素被視為有效。 |
| @DecimalMin(value,inclusive) | 限制必須為一個(gè)不小于指定值的value數(shù)字,inclusive:最大值是否包括 | 同上 |
| @Digits(integer,fraction) | 必須是接受范圍內(nèi)的數(shù)字,且整數(shù)部分的位數(shù)不能超過integer,小數(shù)部分的位數(shù)不能超過fraction | 同上 |
| @Max(value) | 限制必須為一個(gè)不大于指定值的數(shù)字 | 同上 |
| @Min(value) | 限制必須為一個(gè)不小于指定值的數(shù)字 | 同上 |
| @Length(min = 6, max = 16) | 指定傳入的字符串的長(zhǎng)度 | 字符串 |
| @Size(max,min) | 限制字符長(zhǎng)度必須在min到max之間 【不是數(shù)字】 | 同notempty,集合類數(shù)組和字符 |
| @Range | 帶批注的元素必須在適當(dāng)?shù)姆秶鷥?nèi)。 | 應(yīng)用于數(shù)值或數(shù)值的字符串表示形式。 |
基于正則類型
| 注解 | 限制 | 類型 |
|---|---|---|
| @Pattern(value) | 限制必須符合指定的正則表達(dá)式 | CharSequence,null有效 |
| 驗(yàn)證注解的元素值是Email,可選值regexp,flags也可以通過正則表達(dá)式和flag指定自定義的email格式。因?yàn)槊總€(gè)人要求的郵箱可能格式也不一樣,如我可以通過regexp設(shè)置后綴必須為@qq.com | CharSequence,null有效 | |
| @CreditCardNumber | 信用卡校驗(yàn) | 同上 |
| @URL | 批注的字符串是否為 URL基于正則表達(dá)式的 。 | 同上 |
| @UUID | 批注的字符序列是否為有效的 UUID,version指定版本variant變體,letterCase所需的字母大小寫 默認(rèn)情況下只有小寫有效,allowNil如果 nil UUID 有效 根據(jù)默認(rèn)值 nil UUID 00000000-0000-0000-0000-000000000000 有效,allowEmpty允許空字符串。默認(rèn)情況下不允許空字符串 |
腳本注解
@ScriptAssert
它根據(jù)批注元素計(jì)算腳本表達(dá)式。此約束可用于實(shí)現(xiàn)驗(yàn)證例程,腳本表達(dá)式可以用任何腳本或表達(dá)式語(yǔ)言編寫,在類路徑上可以找到 JSR 223 (“JavaTM 平臺(tái)腳本”)兼容引擎。下面的清單顯示了使用 JDK 附帶的 JavaScript 引擎的示例:
我看到的時(shí)候給我震驚了一下,他注解寫的啥??任何表達(dá)式語(yǔ)言??不過可能是我沒見過世面,或者是知識(shí)點(diǎn)用的少,java6就支持JavaScript。不過一般很少用吧。
下面是一個(gè)校驗(yàn)時(shí)間的腳本
@ScriptAssert(lang = "javascript", script = "_this.startDate.before(_this.endDate)")
public class CalendarEvent {
private Date startDate;
private Date endDate;
//...
}注意!??!java11開始就移除了NashornScriptEngineFactory,所以11以上需要添加依賴才可以使用javascript需要新增
<dependency>
<groupId>org.openjdk.nashorn</groupId>
<artifactId>nashorn-core</artifactId>
<version>15.4</version>
</dependency>沒有通過

修改時(shí)間通過了

Valid與Validated區(qū)別
Validated是Valid的加強(qiáng)版
使用范圍
經(jīng)過我的層層驗(yàn)證
- controller類上:
- 在controller類上只有使用validated,將開啟所有的路徑參數(shù)驗(yàn)證,對(duì)實(shí)體類(路徑和body)無(wú)效
- 方法上:
- 全部無(wú)效,無(wú)論是路徑還說(shuō)body,2個(gè)注解都沒用。
- 入?yún)⑸希?/li>
- 只有在對(duì)body或者路徑參數(shù)實(shí)體類或者添加注解才有效,2個(gè)都有效,對(duì)單獨(dú)的類型無(wú)效
- 實(shí)體類的屬性上
- Valid有效,且路徑參數(shù)有效,body無(wú)效,body需要自己參數(shù)開啟,無(wú)論參數(shù)是否加驗(yàn)證注解
兩者是否能用于成員屬性(字段)上直接影響能否提供嵌套驗(yàn)證的功能。
分組
@Validated:提供了一個(gè)分組功能,可以在入?yún)Ⅱ?yàn)證時(shí),根據(jù)不同的分組采用不同的驗(yàn)證機(jī)制。沒有添加分組屬性時(shí),默認(rèn)驗(yàn)證沒有分組的驗(yàn)證屬性。Valid是不能進(jìn)行分組的,靈活性更差。
public class DemoQuery {
@Length(max = 10, min = 2,groups = {Demo1.class, Demo2.class},message = "name長(zhǎng)度不符合要求")
private String name;
@Min(value = 10,groups = {Demo1.class}) @Max(100)
@NotNull
private Integer age;
} @PostMapping("/post2")
public String post2(@Validated({Demo2.class}) @RequestBody DemoQuery query, @NotNull String id) {
System.out.println("name = " + query.getName());
System.out.println("age = " + query.getAge());
System.out.println("id = " + id);
return "ok";
}不通過

通過

改為demo1

嵌套驗(yàn)證
新增一個(gè)類
@Data
public class NestedQuery {
@NotNull
private String id;
@Valid
@NotNull
private DemoQuery querys;
} @GetMapping("/nested")
public String nested(@Validated NestedQuery query, BindingResult bindingResult) {
System.out.println("id = " + query.getId());
System.out.println("query = " + query.getQuerys());
System.out.println(bindingResult);
return "ok";
}發(fā)送返回的居然是ok,

但是在控制臺(tái),驗(yàn)證說(shuō)出錯(cuò)了,說(shuō)明嵌套的錯(cuò)誤不會(huì)直接返回,而是會(huì)記錄。需要自己處理一下。

如
Assert.isTrue(!bindingResult.hasErrors(),"參數(shù)錯(cuò)誤");

結(jié)束:收工,累死了。
到此這篇關(guān)于spring boot validation參數(shù)校驗(yàn)及分組嵌套各種類型及使用小結(jié)的文章就介紹到這了,更多相關(guān)spring boot validation參數(shù)校驗(yàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot + validation 接口參數(shù)校驗(yàn)的思路詳解
- Spring?Boot集成validation實(shí)現(xiàn)參數(shù)校驗(yàn)功能
- SpringBoot使用Validation包進(jìn)行輸入?yún)?shù)校驗(yàn)
- springboot中使用Hibernate-Validation校驗(yàn)參數(shù)詳解
- SpringBoot使用Validation進(jìn)行參數(shù)校驗(yàn)的示例詳解
- spring-boot-starter-validation?校驗(yàn)參數(shù)的實(shí)現(xiàn)
- spring boot輸入數(shù)據(jù)校驗(yàn)(validation)的實(shí)現(xiàn)過程
- 從零到掌握Spring Boot Validation 接口校驗(yàn)的詳細(xì)過程
相關(guān)文章
Spring AOP日志框架實(shí)現(xiàn)過程圖解
這篇文章主要介紹了Spring AOP日志框架實(shí)現(xiàn)過程圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
MapStruct實(shí)體間轉(zhuǎn)換的簡(jiǎn)單用法
今天小編就為大家分享一篇關(guān)于MapStruct實(shí)體間轉(zhuǎn)換的簡(jiǎn)單用法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03
Java實(shí)現(xiàn)SM3加密和驗(yàn)證的示例代碼
在商用密碼體系中,SM3主要用于數(shù)字簽名及驗(yàn)證、消息認(rèn)證碼生成及驗(yàn)證、隨機(jī)數(shù)生成等,其算法公開,本文給大家詳細(xì)介紹了使用Java實(shí)現(xiàn)SM3加密和驗(yàn)證,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2023-12-12
Spring框架學(xué)習(xí)筆記之方法注解@Bean的使用
這篇文章主要給大家介紹了關(guān)于Spring框架學(xué)習(xí)筆記之方法注解@Bean使用的相關(guān)資料,這是一個(gè)我們很常用的注解,作用是指示一個(gè)方法生成一個(gè)由Spring管理的Bean,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
PageHelper插件實(shí)現(xiàn)一對(duì)多查詢時(shí)的分頁(yè)問題
這篇文章主要介紹了PageHelper插件實(shí)現(xiàn)一對(duì)多查詢時(shí)的分頁(yè)問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04

