spring?boot?validation參數校驗與分組嵌套各種類型及使用小結
寫在前面:
參數校驗基本上是controller必做的事情,畢竟前端傳過來的一切都不可信。 但是每次if(StrUtil.isNotNull())啥的有時候多還難寫。validation可以簡化這一操作。
項目構建
采用boot3,主要依賴為spring web 和validation
主要依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
項目結構
問題展示
先來個簡單的案例
@RestController public class ValidationController { @GetMapping("/get") public String get(String name,String age){ System.out.println(name); System.out.println(age); return "ok"; } }
點擊這個就可以發(fā)送請求了
發(fā)送出去不會做任何校驗
這個的處理我們可以選擇加上@RequestParam注解。@RequestParam默認屬性require為true,就是必須要傳值,
public String get(@RequestParam String name,@RequestParam String age)
報錯返回
封裝成實體類也是一樣的。
但是這樣只能做非null判斷,不能做復雜的判斷。在body里面的時候更加不會校驗了
validation使用
那么validation又如何做到呢。
快速入門
需求:get請求中,name長度在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一點用沒有。
我查資料發(fā)現需要參數前面加上啟動校驗@Validated或者@Valid注解,但是無論我怎么放到都是沒有校驗。全部無效。
我之前研究了半天,然后才發(fā)現,如果想要這樣校驗的話,需要在controller類上面加上@Validated且Valid都不行。
如果是實體類接收就不一樣了。直接在方法就可以了
注釋
到這里基本使用應該就差不多知道了。現在來進行注解的學習。
注解通用屬性基本上都有的
屬性 | 描述 |
---|---|
message | 錯誤返回描述 |
groups | 分組,可以進行更加靈活的選擇。 |
payload |
無參注解,無必須傳的值
注解 | 限制 | 類型 |
---|---|---|
@Null | 限制只能為null | 接收任何類型,這個應該用的比較少 |
@NotNull | 限制必須不為null | 接收任何類型 |
@AssertFalse | 限制必須為false | 支持的類型包括 boolean 和 Boolean。null 元素被視為有效。 |
@AssertTrue | 限制必須為true | 支持的類型包括 boolean 和 Boolean。null 元素被視為有效。 |
@Future | 限制必須是一個將來的日期 | 大部分的時間類如果Date、Calendar、Instant、LocalDate等。null 元素被視為有效 |
@Past | 限制必須是過去的時刻、日期或時間 | 和上面一樣 |
@PastOrPresent | 帶注釋的元素必須是過去或現在的時刻、日期或時間 | 同上 |
@NotEmpty | 帶批注的元素不得為 null和空 | CharSequence(計算字符序列的長度)Collection (集合大?。㎝ap (大小)數組(計算數組長度) |
@NotBlank | 帶批注的元素不得且 null 必須至少包含一個非空格字符 | CharSequence |
@Positive | 帶注釋的元素必須是嚴格的正數(即 0 被視為無效值)。 | BigDecimal、BigInteger、byteintlong、 short及其floatdouble各自的包裝器 |
@PositiveOrZero | 正數或0 | 同上 |
大小注解,用于限值大小
注解 | 限制 | 類型 |
---|---|---|
@DecimalMax(value,inclusive) | 限制必須為一個不大于指定值的value數字,inclusive:指定指定的最小值是包含的還是排除的true為不包括最小值 | BigDecimal、BigInteger、CharSequence、byte、 shortintlong及其各自的包裝器,請注意, double 由于舍入錯誤,不支持 (某些 float 提供程序可能會提供一些近似支持)。null 元素被視為有效。 |
@DecimalMin(value,inclusive) | 限制必須為一個不小于指定值的value數字,inclusive:最大值是否包括 | 同上 |
@Digits(integer,fraction) | 必須是接受范圍內的數字,且整數部分的位數不能超過integer,小數部分的位數不能超過fraction | 同上 |
@Max(value) | 限制必須為一個不大于指定值的數字 | 同上 |
@Min(value) | 限制必須為一個不小于指定值的數字 | 同上 |
@Length(min = 6, max = 16) | 指定傳入的字符串的長度 | 字符串 |
@Size(max,min) | 限制字符長度必須在min到max之間 【不是數字】 | 同notempty,集合類數組和字符 |
@Range | 帶批注的元素必須在適當的范圍內。 | 應用于數值或數值的字符串表示形式。 |
基于正則類型
注解 | 限制 | 類型 |
---|---|---|
@Pattern(value) | 限制必須符合指定的正則表達式 | CharSequence,null有效 |
驗證注解的元素值是Email,可選值regexp,flags也可以通過正則表達式和flag指定自定義的email格式。因為每個人要求的郵箱可能格式也不一樣,如我可以通過regexp設置后綴必須為@qq.com | CharSequence,null有效 | |
@CreditCardNumber | 信用卡校驗 | 同上 |
@URL | 批注的字符串是否為 URL基于正則表達式的 。 | 同上 |
@UUID | 批注的字符序列是否為有效的 UUID,version指定版本variant變體,letterCase所需的字母大小寫 默認情況下只有小寫有效,allowNil如果 nil UUID 有效 根據默認值 nil UUID 00000000-0000-0000-0000-000000000000 有效,allowEmpty允許空字符串。默認情況下不允許空字符串 |
腳本注解
@ScriptAssert
它根據批注元素計算腳本表達式。此約束可用于實現驗證例程,腳本表達式可以用任何腳本或表達式語言編寫,在類路徑上可以找到 JSR 223 (“JavaTM 平臺腳本”)兼容引擎。下面的清單顯示了使用 JDK 附帶的 JavaScript 引擎的示例:
我看到的時候給我震驚了一下,他注解寫的啥??任何表達式語言??不過可能是我沒見過世面,或者是知識點用的少,java6就支持JavaScript。不過一般很少用吧。
下面是一個校驗時間的腳本
@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>
沒有通過
修改時間通過了
Valid與Validated區(qū)別
Validated是Valid的加強版
使用范圍
經過我的層層驗證
- controller類上:
- 在controller類上只有使用validated,將開啟所有的路徑參數驗證,對實體類(路徑和body)無效
- 方法上:
- 全部無效,無論是路徑還說body,2個注解都沒用。
- 入參上:
- 只有在對body或者路徑參數實體類或者添加注解才有效,2個都有效,對單獨的類型無效
- 實體類的屬性上
- Valid有效,且路徑參數有效,body無效,body需要自己參數開啟,無論參數是否加驗證注解
兩者是否能用于成員屬性(字段)上直接影響能否提供嵌套驗證的功能。
分組
@Validated:提供了一個分組功能,可以在入參驗證時,根據不同的分組采用不同的驗證機制。沒有添加分組屬性時,默認驗證沒有分組的驗證屬性。Valid是不能進行分組的,靈活性更差。
public class DemoQuery { @Length(max = 10, min = 2,groups = {Demo1.class, Demo2.class},message = "name長度不符合要求") 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
嵌套驗證
新增一個類
@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,
但是在控制臺,驗證說出錯了,說明嵌套的錯誤不會直接返回,而是會記錄。需要自己處理一下。
如
Assert.isTrue(!bindingResult.hasErrors(),"參數錯誤");
結束:收工,累死了。
到此這篇關于spring boot validation參數校驗及分組嵌套各種類型及使用小結的文章就介紹到這了,更多相關spring boot validation參數校驗內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!