springboot Validated失效的問(wèn)題及解決思路
1、 pom 加入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2、實(shí)體類加入注解
@Data
@Accessors(chain = true)
@TableName("user")
@Validated
public class User {
private Integer id;
@NotBlank(message = "姓名不能為空")
private String name;
@Min(message = "年齡不正確1-100之間",value = 1)
@Max(message = "年齡不正確1-100之間",value = 1)
private Integer age ;
private Integer sex;
}

3、控制器加入@Valid注解

4、測(cè)試效果

常見的注解
通常情況下,在javax.validation.constraints 包下,定義了一系列的約束(constraint)注解,一共 22 個(gè)注解,快速略過(guò)即可。如下:
空和非空檢查
- @NotBlank:只能用于字符串不為 null ,并且字符串 .trim() 以后 length 要大于 0 。
- @NotEmpty:集合對(duì)象的元素不為 0 ,即集合不為空 。
- @NotNull:不能為 null 。
- @Null`:必須為 null 。
數(shù)值檢查
@DecimalMax(value):被注釋的元素必須是一個(gè)數(shù)字,其值必須小于等于指定的最大值。@DecimalMin(value):被注釋的元素必須是一個(gè)數(shù)字,其值必須大于等于指定的最小值。@Digits(integer, fraction):被注釋的元素必須是一個(gè)數(shù)字,其值必須在可接受的范圍內(nèi)。@Positive:判斷正數(shù)。@PositiveOrZero:判斷正數(shù)或 0 。@Max(value):該字段的值只能小于或等于該值。@Min(value):該字段的值只能大于或等于該值。@Negative:判斷負(fù)數(shù)。@NegativeOrZero:判斷負(fù)數(shù)或 0 。
Boolean 值檢查
@AssertFalse:被注釋的元素必須為 true 。@AssertTrue:被注釋的元素必須為 false 。
長(zhǎng)度檢查
- @Size(max, min):檢查字段的 size 是否在 min 和 max 之間,可以是字符串、數(shù)組、集合、Map 等。
日期檢查
- @Future:被注釋的元素必須是一個(gè)將來(lái)的日期。
- @FutureOrPresent:判斷日期是否是將來(lái)或現(xiàn)在日期。
- @Past:檢查該字段的日期是在過(guò)去。
- @PastOrPresent:判斷日期是否是過(guò)去或現(xiàn)在日期。
其它檢查
- @Email:被注釋的元素必須是電子郵箱地址。
- @Pattern(value):被注釋的元素必須符合指定的正則表達(dá)式。
Hibernate Validator 附加的約束注解,在org.hibernate.validator.constraints 包下,定義了一系列的約束(constraint)注解。常見的如示。
- @Range(min=, max=):被注釋的元素必須在合適的范圍內(nèi)。
- @Length(min=, max=):被注釋的字符串的大小必須在指定的范圍內(nèi)。
- @URL(protocol=,host=,port=,regexp=,flags=):被注釋的字符串必須是一個(gè)有效的 URL 。
- @SafeHtml:判斷提交的 HTML 是否安全。例如說(shuō),不能包含 javascript 腳本等等。
其他的就不一一列舉了,有感興趣的小伙伴可以去源碼包看看。
@Valid 和 @Validated
@Valid 注解,是 Bean Validation 所定義,可以添加在普通方法、構(gòu)造方法、方法參數(shù)、方法返回、成員變量上,表示它們需要進(jìn)行約束校驗(yàn)。
@Validated 注解,是 Spring Validation 鎖定義,可以添加在類、方法參數(shù)、普通方法上,表示它們需要進(jìn)行約束校驗(yàn)。同時(shí),@Validated 有 value 屬性,支持分組校驗(yàn)。
對(duì)于初學(xué)者來(lái)說(shuō),很容易搞混 @Valid 和 @Validated 注解。
- ① 聲明式校驗(yàn):Spring Validation 僅對(duì) @Validated 注解,實(shí)現(xiàn)聲明式校驗(yàn)。
- ② 分組校驗(yàn):Bean Validation 提供的 @Valid注解,因?yàn)闆](méi)有分組校驗(yàn)的屬性,所以無(wú)法提供分組校驗(yàn)。此時(shí),我們只能使用 @Validated 注解。
- ③ 嵌套校驗(yàn):相比來(lái)說(shuō),@Valid注解的地方,多了【成員變量】。這就導(dǎo)致,如果有嵌套對(duì)象的時(shí)候,只能使用@Valid注解。
自定義校驗(yàn)注解
雖然 JSR303 和 Hibernate Validtor 已經(jīng)提供了很多校驗(yàn)注解,但是當(dāng)面對(duì)復(fù)雜參數(shù)校驗(yàn)時(shí),還是不能滿足我們的要求,這時(shí)候我們就需要 自定義校驗(yàn)注解。
下面以“List數(shù)組中不能含有null元素”為實(shí)例自定義校驗(yàn)注解
1、注解定義如示。
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = ListNotHaveNullValidatorImpl.class)//此處指定了注解的實(shí)現(xiàn)類
public @interface ListNotHaveNull {
/**
* 添加value屬性,可以作為校驗(yàn)時(shí)的條件,若不需要,可去掉此處定義
*/
int value() default 0;
String message() default "List集合中不能含有null元素";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* 定義List,為了讓Bean的一個(gè)屬性上可以添加多套規(guī)則
*/
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@interface List {
ListNotHaveNull[] value();
}
}
2、編寫自定義校驗(yàn)實(shí)現(xiàn)類
@Service
public class ListNotHaveNullValidatorImpl implements ConstraintValidator<ListNotHaveNull, List> {
private int value;
@Override
public void initialize(ListNotHaveNull constraintAnnotation) {
//傳入value 值,可以在校驗(yàn)中使用
this.value = constraintAnnotation.value();
}
public boolean isValid(List list, ConstraintValidatorContext constraintValidatorContext) {
for (Object object : list) {
if (object == null) {
//如果List集合中含有Null元素,校驗(yàn)失敗
return false;
} else if (object instanceof String) {
String value = object.toString();
if (value.trim().length() == 0){
return false;
}
}
}
return true;
}
}
3、model中添加注解:
@Data
public class SysRole {
private Long roleId;
@NotBlank(message = "角色名不能為空")
private String name;
@NotEmpty(message = "資源列表不能為空")
@ListNotHaveNull(message = "List 中不能含有null元素")
@Valid
private List<String> paths;
}
4、編寫前端控制器
@PostMapping("/addRole")
public R addRole(@RequestBody @Valid SysRole sysRole) {
System.out.println("走到這里說(shuō)明校驗(yàn)成功");
System.out.println(sysRole);
return R.ok(R.SUCCESS_MSG);
}
使用方法同 “簡(jiǎn)單校驗(yàn)”,在在需要校驗(yàn)的Model上面加上@Valid即可。
通用的Validtor校驗(yàn)工具類
public class ValidatorUtils {
private ValidatorUtils() { }
private static Validator validator;
static {
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
/**
* 校驗(yàn)對(duì)象
*
* @param object 待校驗(yàn)對(duì)象
* @param groups 待校驗(yàn)的組
* @throws RRException 校驗(yàn)不通過(guò),則報(bào)RRException異常
*/
public static void validateEntity(Object object, Class<?>... groups) throws RRException {
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
Iterator<ConstraintViolation<Object>> iterator = constraintViolations.iterator();
StringBuilder msg = new StringBuilder();
while (iterator.hasNext()) {
ConstraintViolation<Object> constraint = iterator.next();
msg.append(constraint.getMessage()).append(',');
}
throw new RRException(msg.toString().substring(0,msg.toString().lastIndexOf(',')));
}
}
}
使用方式,在接收到前端傳遞的參數(shù)后,使用ValidatorUtils.validateEntity(【參數(shù)名】);即可校驗(yàn),支持分組校驗(yàn),分組需要定義分組接口。
springboot2 @RequestBody @Valid校驗(yàn)失效問(wèn)題
這是因?yàn)?@RequestBody @Valid 拋出的異常沒(méi)有被捕獲,所以需要建立一個(gè)全局自定義異常處理類

@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public Result MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e)
{
//獲取實(shí)體類定義的校驗(yàn)注解字段上的message作為異常信息,@NotBlank(message = "用戶密碼不能為空!")異常信息即為"用戶密碼不能為空!"
List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
String message = allErrors.stream().map(s -> s.getDefaultMessage()).collect(Collectors.joining(";"));
List<String> msgList = new ArrayList<>();
msgList = Arrays.asList(message.split(";"));
return Result.failed(msgList.get(0));
}
}

測(cè)試

校驗(yàn)GET請(qǐng)求
這種情況下,使用@Valid和@Validated都可以。
requestParam/PathVariable參數(shù)校驗(yàn)
GET請(qǐng)求一般會(huì)使用requestParam或PathVariable傳參。如果參數(shù)比較多(比如超過(guò)6個(gè)),還是推薦使用DTO對(duì)象接收。否則,推薦將一個(gè)個(gè)參數(shù)平鋪到方法入?yún)⒅小T谶@種情況下,必須在Controller類上標(biāo)注@Validated注解,并在入?yún)⑸下暶骷s束注解(如@Min等)。如果校驗(yàn)失敗,會(huì)拋出ConstraintViolationException異常。代碼示例如下:
校驗(yàn)GET必要條件
1、Controller類上標(biāo)注@Validated注解
2、全局捕獲該異常
@ExceptionHandler({ConstraintViolationException.class})
@ResponseBody
public Result handleConstraintViolationException(ConstraintViolationException ex) {
return Result.failed(ex.getMessage());
}

3、如何GET請(qǐng)求requestParam 則@RequestParam(value = “customerId”) 不能添加該注解

4、如何GET請(qǐng)求PathVariable 則需加上@PathVariable()

總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- SpringBoot使用@Valid或者@Validated時(shí)自定義校驗(yàn)的場(chǎng)景分析
- SpringBoot參數(shù)校驗(yàn)@Validated、@Valid方式詳解
- SpringBoot利用@Validated注解優(yōu)雅實(shí)現(xiàn)參數(shù)校驗(yàn)
- SpringBoot參數(shù)校驗(yàn):@Valid與@Validated使用詳解
- SpringBoot參數(shù)校驗(yàn)之@Valid與@Validated的用法與場(chǎng)景
- SpringBoot中利用@Valid和@Validated進(jìn)行參數(shù)校驗(yàn)
相關(guān)文章
詳解Java實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)之并查集
并查集這種數(shù)據(jù)結(jié)構(gòu),可能出現(xiàn)的頻率不是那么高,但是還會(huì)經(jīng)常性的見到,其理解學(xué)習(xí)起來(lái)非常容易,通過(guò)本文,一定能夠輕輕松松搞定并查集2021-06-06
J2ee 高并發(fā)情況下監(jiān)聽器實(shí)例詳解
這篇文章主要介紹了J2ee 高并發(fā)情況下監(jiān)聽器實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-02-02
Jenkins配置自動(dòng)發(fā)送郵件過(guò)程圖解
這篇文章主要介紹了jenkins配置自動(dòng)發(fā)送郵件過(guò)程圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Spring之spring-context-indexer依賴詳解
這篇文章主要介紹了Spring之spring-context-indexer依賴詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
java實(shí)現(xiàn)Fibonacci算法實(shí)例
這篇文章主要介紹了java實(shí)現(xiàn)Fibonacci算法的方法,以實(shí)例形式較為詳細(xì)的分析了java實(shí)現(xiàn)Fibonacci算法的原理與相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09
Java Metrics系統(tǒng)性能監(jiān)控工具的使用詳解
Metrics是一個(gè)Java庫(kù),可以對(duì)系統(tǒng)進(jìn)行監(jiān)控,統(tǒng)計(jì)一些系統(tǒng)的性能指標(biāo)。本文就來(lái)和大家詳細(xì)聊聊這個(gè)工具的具體使用,希望對(duì)大家有所幫助2022-11-11

