springboot Validated失效的問題及解決思路
1、 pom 加入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2、實體類加入注解
@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、測試效果

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

@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
@ResponseBody
public Result MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e)
{
//獲取實體類定義的校驗注解字段上的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));
}
}

測試

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

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

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

總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解Java實現(xiàn)數(shù)據(jù)結(jié)構(gòu)之并查集
并查集這種數(shù)據(jù)結(jié)構(gòu),可能出現(xiàn)的頻率不是那么高,但是還會經(jīng)常性的見到,其理解學(xué)習(xí)起來非常容易,通過本文,一定能夠輕輕松松搞定并查集2021-06-06
Spring之spring-context-indexer依賴詳解
這篇文章主要介紹了Spring之spring-context-indexer依賴詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11
Java Metrics系統(tǒng)性能監(jiān)控工具的使用詳解
Metrics是一個Java庫,可以對系統(tǒng)進(jìn)行監(jiān)控,統(tǒng)計一些系統(tǒng)的性能指標(biāo)。本文就來和大家詳細(xì)聊聊這個工具的具體使用,希望對大家有所幫助2022-11-11

