日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

element form自定义校验_SpringBoot分组校验及自定义校验注解

發(fā)布時間:2023/12/10 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 element form自定义校验_SpringBoot分组校验及自定义校验注解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

??在日常的開發(fā)中,參數(shù)校驗是非常重要的一個環(huán)節(jié),嚴(yán)格參數(shù)校驗會減少很多出bug的概率,增加接口的安全性。在此之前寫過一篇SpringBoot統(tǒng)一參數(shù)校驗主要介紹了一些簡單的校驗方法。而這篇則是介紹一些進階的校驗方式。比如說:在某個接口編寫的過程中肯定會遇到,當(dāng)xxType值為A,paramA值必傳。xxType值為B,paramB值必須傳。對于這樣的,通常的做法就是在controller加上各種if判斷。顯然這樣的代碼是不夠優(yōu)雅的,而分組校驗及自定義參數(shù)校驗,就是來解決這個問題的。

PathVariable參數(shù)校驗

??Restful的接口,在現(xiàn)在來講應(yīng)該是比較常見的了,常用的地址欄的參數(shù),我們都是這樣校驗的。

/**
?*?獲取電話號碼信息
?*/
@GetMapping("/phoneInfo/{phone}")
public?ResultVo?phoneInfo(@PathVariable("phone")?String?phone){
????//?驗證電話號碼是否有效
????String?pattern?=?"^[1][3,4,5,7,8][0-9]{9}$";
????boolean?isValid?=??Pattern.matches(pattern,?phone);
????if(isValid){
????????//?執(zhí)行相應(yīng)邏輯
????????return?ResultVoUtil.success(phone);
????}?else?{
????????//?返回錯誤信息
????????return?ResultVoUtil.error("手機號碼無效");
????}
}

很顯然上面的代碼不夠優(yōu)雅,所以我們可以在參數(shù)后面,添加對應(yīng)的正則表達式phone:正則表達式來進行驗證。這樣就省去了在controller編寫校驗代碼了。

/**
?*?獲取電話號碼信息
?*/
@GetMapping("/phoneInfo/{phone:^[1][3,4,5,7,8][0-9]{9}$}")
public?ResultVo?phoneInfo(@PathVariable("phone")?String?phone){
????return?ResultVoUtil.success(phone);
}

雖然這樣處理后代碼更精簡了。但是如果傳入的手機號碼,不符合規(guī)則會直接返回404。而不是提示手機號碼錯誤。錯誤信息如下:

自定義校驗注解

??我們以校驗手機號碼為例,雖然validation提供了@Pattern這個注解來使用正則表達式進行校驗。如果被使用在多處,一旦正則表達式發(fā)生更改,則需要一個一個的進行修改。很顯然為了避免做這樣的無用功,自定義校驗注解就是你的好幫手。

@Data
public?class?PhoneForm?{

????/**
?????*?電話號碼
?????*/
????@Pattern(regexp?=?"^[1][3,4,5,7,8][0-9]{9}$"?,?message?=?"電話號碼有誤")
????private?String?phone;

}

??要實現(xiàn)一個自定義校驗注解,主要是有兩步。一是注解本身,二是校驗邏輯實現(xiàn)類

PhoneVerify 校驗注解

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy?=?PhoneValidator.class)
public?@interface?Phone?{
?
????String?message()?default?"手機號碼格式有誤";

????Class>[]?groups()?default?{};

????Class?extends?Payload>[]?payload()?default?{};

}

PhoneValidator 校驗實現(xiàn)類

public?class?PhoneValidator?implements?ConstraintValidator<Phone,?Object>?{

????@Override
????public?boolean?isValid(Object?telephone,?ConstraintValidatorContext?constraintValidatorContext)?{
????????String?pattern?=?"^1[3|4|5|7|8]\\d{9}$";
????????return?Pattern.matches(pattern,?telephone.toString());
????}
}

CustomForm 表單數(shù)據(jù)

@Data
public?class?CustomForm?{

????/**
?????*?電話號碼
?????*/
????@Phone
????private?String?phone;

}

測試接口

@PostMapping("/customTest")
public?ResultVo?customTest(@RequestBody?@Validated?CustomForm?form){
?return?ResultVoUtil.success(form.getPhone());
}

注解的含義

@Target({ElementType.FIELD})

??注解是指定當(dāng)前自定義注解可以使用在哪些地方,這里僅僅讓他可以使用屬性上。但還可以使用在更多的地方,比如說方法上、構(gòu)造器上等等。

  • TYPE - 類,接口(包括注解類型)或枚舉
  • FIELD - 字段(包括枚舉常量)
  • METHOD - 方法
  • PARAMETER - 參數(shù)
  • CONSTRUCTOR - 構(gòu)造函數(shù)
  • LOCAL_VARIABLE - 局部變量
  • ANNOTATION_TYPE -注解類型
  • PACKAGE - 包
  • TYPE_PARAMETER - 類型參數(shù)
  • TYPE_USE - 使用類型
@Retention(RetentionPolicy.RUNTIME)

??指定當(dāng)前注解保留到運行時。保留策略有下面三種:

  • SOURCE - 注解只保留在源文件,當(dāng)Java文件編譯成class文件的時候,注解被遺棄。
  • CLASS - 注解被保留到class文件,但jvm加載class文件時候被遺棄,這是默認的生命周期。
  • RUNTIME - 注解不僅被保存到class文件中,jvm加載class文件之后,仍然存在。
@Constraint(validatedBy = PhoneValidator.class)

??指定了當(dāng)前注解使用哪個校驗類來進行校驗。

分組校驗

UserForm

@Data
public?class?UserForm?{

????/**
?????*?id
?????*/
????@Null(message?=?"新增時id必須為空",?groups?=?{Insert.class})
????@NotNull(message?=?"更新時id不能為空",?groups?=?{Update.class})
????private?String?id;

????/**
?????*?類型
?????*/
????@NotEmpty(message?=?"姓名不能為空"?,?groups?=?{Insert.class})
????private?String?name;

????/**
?????*?年齡
?????*/
????@NotEmpty(message?=?"年齡不能為空"?,?groups?=?{Insert.class})
????private?String?age;
????
}

Insert分組

public?interface?Insert?{
}

Update分組

public?interface?Update?{
}

測試接口

/**
?*?添加用戶
?*/
@PostMapping("/addUser")
public?ResultVo?addUser(@RequestBody?@Validated({Insert.class})?UserForm?form){
???//?選擇對應(yīng)的分組進行校驗
????return?ResultVoUtil.success(form);
}

/**
?*?更新用戶
?*/
@PostMapping("/updateUser")
public?ResultVo?updateUser(@RequestBody?@Validated({Update.class})?UserForm?form){
????//?選擇對應(yīng)的分組進行校驗
????return?ResultVoUtil.success(form);
}

測試結(jié)果

添加測試
更新測試

順序校驗@GroupSequence

??在@GroupSequence內(nèi)可以指定,分組校驗的順序。比如說@GroupSequence({Insert.class, Update.class, UserForm.class})先執(zhí)行Insert校驗,然后執(zhí)行Update校驗。如果Insert分組,校驗失敗了,則不會進行Update分組的校驗。

@Data
@GroupSequence({Insert.class,?Update.class,?UserForm.class})
public?class?UserForm?{

????/**
?????*?id
?????*/
????@Null(message?=?"新增時id必須為空",?groups?=?{Insert.class})
????@NotNull(message?=?"更新時id不能為空",?groups?=?{Update.class})
????private?String?id;

????/**
?????*?類型
?????*/
????@NotEmpty(message?=?"姓名不能為空"?,?groups?=?{Insert.class})
????private?String?name;

????/**
?????*?年齡
?????*/
????@NotEmpty(message?=?"年齡不能為空"?,?groups?=?{Insert.class})
????private?String?age;

}
測試接口
/**
*?編輯用戶
*/
@PostMapping("/editUser")
public?ResultVo?editUser(@RequestBody?@Validated?UserForm?form){
?return?ResultVoUtil.success(form);
}
測試結(jié)果

??哈哈哈,測試結(jié)果其實是個死循環(huán),不管你咋輸入都會報錯,小伙伴可以嘗試一下哦。上面的例子只是個演示,在實際中還是別這樣做了,需要根據(jù)具體邏輯進行校驗。

自定義分組校驗

??對于之前提到了當(dāng)xxType值為A,paramA值必傳。xxType值為B,paramB值必須傳這樣的場景。單獨使用分組校驗和分組序列是無法實現(xiàn)的。需要使用@GroupSequenceProvider才行。

自定義分組表單

@Data
@GroupSequenceProvider(value?=?CustomSequenceProvider.class)
public?class?CustomGroupForm?{

????/**
?????*?類型
?????*/
????@Pattern(regexp?=?"[A|B]"?,?message?=?"類型不必須為?A|B")
????private?String?type;

????/**
?????*?參數(shù)A
?????*/
????@NotEmpty(message?=?"參數(shù)A不能為空"?,?groups?=?{WhenTypeIsA.class})
????private?String?paramA;

????/**
?????*?參數(shù)B
?????*/
????@NotEmpty(message?=?"參數(shù)B不能為空",?groups?=?{WhenTypeIsB.class})
????private?String?paramB;

????/**
?????*?分組A
?????*/
????public?interface?WhenTypeIsA?{

????}

????/**
?????*?分組B
?????*/
????public?interface?WhenTypeIsB?{

????}

}

CustomSequenceProvider

public?class?CustomSequenceProvider?implements?DefaultGroupSequenceProvider<CustomGroupForm>?{

????@Override
????public?List>?getValidationGroups(CustomGroupForm?form)?{
????????List>?defaultGroupSequence?=?new?ArrayList<>();
????????defaultGroupSequence.add(CustomGroupForm.class);if?(form?!=?null?&&?"A".equals(form.getType()))?{
????????????defaultGroupSequence.add(CustomGroupForm.WhenTypeIsA.class);
????????}if?(form?!=?null?&&?"B".equals(form.getType()))?{
????????????defaultGroupSequence.add(CustomGroupForm.WhenTypeIsB.class);
????????}return?defaultGroupSequence;
????}
}

測試接口

/**
?*?自定義分組
?*/
@PostMapping("/customGroup")
public?ResultVo?customGroup(@RequestBody?@Validated?CustomGroupForm?form){
????return?ResultVoUtil.success(form);
}

測試結(jié)果

Type類型為A
Type類型為B

小結(jié)一下

??GroupSequence注解是一個標(biāo)準(zhǔn)的Bean認證注解。正如之前,它能夠讓你靜態(tài)的重新定義一個類的,默認校驗組順序。然而GroupSequenceProvider它能夠讓你動態(tài)的定義一個校驗組的順序。

注意的一個點

SpringBoot 2.3.x 移除了validation依賴需要手動引入依賴。

<dependency>
??<groupId>org.springframework.bootgroupId>
??<artifactId>spring-boot-starter-validationartifactId>
dependency>

總結(jié)

??個人的一些小經(jīng)驗,參數(shù)的非空判斷,這個應(yīng)該是校驗的第一步了,除了非空校驗,我們還需要做到下面這幾點:

  • 普通參數(shù) - 需要限定字段的長度。如果會將數(shù)據(jù)存入數(shù)據(jù)庫,長度以數(shù)據(jù)庫為準(zhǔn),反之根據(jù)業(yè)務(wù)確定。
  • 類型參數(shù) - 最好使用正則對可能出現(xiàn)的類型做到嚴(yán)格校驗。比如type的值是【0|1|2】這樣的。
  • 列表(list)參數(shù) - 不僅需要對list內(nèi)的參數(shù)是否合格進行校驗,還需要對list的size進行限制。比如說 100。
  • 日期,郵件,金額,URL這類參數(shù)都需要使用對于的正則進行校驗。
  • 參數(shù)真實性 - 這個主要針對于 各種Id 比如說 userId、merchantId,對于這樣的參數(shù),都需要進行真實性校驗,判斷系統(tǒng)內(nèi)是有含有,并且對應(yīng)的狀態(tài)是否正常。

??參數(shù)校驗越嚴(yán)格越好,嚴(yán)格的校驗規(guī)則不僅能減少接口出錯的概率,同時還能避免出現(xiàn)臟數(shù)據(jù),從而來保證系統(tǒng)的安全性和穩(wěn)定性。

錯誤的提醒信息需要友好一點哦,防止等下被前端大哥吐槽哦。

上期回顧

  • SpringBoot統(tǒng)一參數(shù)校驗

結(jié)尾

??如果覺得對你有幫助,可以多多評論,多多點贊哦,也可以到我的主頁看看,說不定有你喜歡的文章,也可以隨手點個關(guān)注哦,謝謝。

??我是不一樣的科技宅,每天進步一點點,體驗不一樣的生活。我們下期見!

總結(jié)

以上是生活随笔為你收集整理的element form自定义校验_SpringBoot分组校验及自定义校验注解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。