Java中的三種校驗注解的使用(@Valid,@Validated和@PathVariable)
更新時間:2022年04月27日 11:06:13 作者:攻城獅Chova
本文主要介紹了Java中的三種校驗注解的使用(@Valid,@Validated和@PathVariable),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
@Valid和@Validated
@Valid和@Validated比較
- 相同點:
- @Valid注解和 @Validated注解都是開啟校驗功能的注解
- 不同點:
- @Validated注解是Spring基于 @Valid注解的進一步封裝,并提供比如分組,分組順序的高級功能
- 使用位置不同:
- @Valid注解 : 可以使用在方法,構(gòu)造函數(shù),方法參數(shù)和成員屬性上
- @Validated注解 : 可以用在類型,方法和方法參數(shù)上. 但是不能用在成員屬性上
@Valid高級使用
@Valid級聯(lián)校驗
- 級聯(lián)校驗: 也叫嵌套檢測.嵌套就是一個實體類包含另一個實體類
- @Valid和可以用在成員屬性的字段上,因此 @Valid可以提供級聯(lián)校驗
- 示例:
@Data public class Hair { @NotBlank(message = "頭發(fā)長度必須提交!") private Double length; @NotBlank(message = "頭發(fā)顏色必須提交!") private String color; } @Data public class Person { @NotBlank(message = "用戶姓名必須提交!") @Size(min=2, max=8) private String userName; // 添加@Valid注解實現(xiàn)嵌套檢測 @Valid @NotEmpty(message = "用戶要有頭發(fā)!") private List<Hair> hairs; } @PostMapping("/person") public Result addPerson(@Valid @RequestBody Person person) { return Result.buildSuccess(person); }- 只是在方法參數(shù)前面添加 @Valid和 @Validated注解,不會對嵌套的實體類進行校驗.要想實現(xiàn)對嵌套的實體類進行校驗,需要在嵌套的實體類屬性上添加 @Valid注解
@Validated高級使用
@Validated分組校驗
- 分組校驗:
- 對指定的組開啟校驗,可以分別作用于不同的業(yè)務(wù)場景中
- 分組校驗是由 @Validated注解中的value提供的
- groups:
- JSR 303校驗注解中的分組方法groups
- 示例:
@Data public class PersonGroup { public interface AddGroup {} public interface UpdateGroup {} // @Validated注解value方法指定分組UpdateGroup.class時校驗 @NotBlank(message = "用戶ID必須提交!", groups = UpdateGroup.class) private String id; // @Validated注解value方法指定分組AddGroup.class或者分組UpdateGroup.class時校驗 @NotBlank(message = "用戶的姓名必須提交!", groups = {AddGroup.class, UpdateGroup.class}) private String name; // @Validated注解value方法未指定分組時校驗 @Range(min = 1, max = 200, message = "用戶的年齡必須提交!") private int age; } - 開啟分組校驗: 通過 @Validated注解的value方法對指定的分組開啟校驗
@RestController
@RequestMapping("/person")
public class PersonGroupController {
// 不指定分組時校驗
@GetMapping("/person")
public Result getPerson(@Validated @RequestBody PersonGroup person) {
return Result.buildSuccess(person);
}
// 指定AddGroup分組校驗
@PostMapping("/person")
public Result addPerson(@Validated(value = PersonGroup.AddGroup.class) @RequestBody PersonGroup person) {
return Result.buildSuccess(person);
}
// 指定UpdateGroup分組校驗
@PutMapping("/person")
public Result updatePerson(@Validated(value = PersonGroup.updateGroup.class) @RequestBody PersonGroup person) {
return Result.buildSuccess(person);
}
}- 校驗方法添加groups的值來指定分組,只有使用 @Validated注解的value的值指定這個分組時,開會開啟注解的校驗數(shù)據(jù)的功能
@Validated分組校驗順序
- 默認情況下,分組間的約束是無序的,但是在一些特殊的情況下可能對分組間的校驗有一定的順序
- 比如第二組的分組的約束的校驗需要依賴第一組的穩(wěn)定狀態(tài)來進行,此時,要求分組間的約束校驗一定要有順序
- 分組校驗順序通過使用 @GroupSequence注解實現(xiàn)
- 示例:
@Data
public class UserGroupSequence {
public interface FirstGroup {}
public interface SecondGroup {}
// 使用GroupSequence定義分組校驗順序:按照FirstGroup,SecondGroup分組順序進行校驗
@GroupSequence({FirstGroup.class, SecondGroup.class})
public interface Group {}
@NotEmpty(message = "用戶ID必須提交!", group = FirstGroup.class)
private String userId;
@NotEmpty(message = "用戶姓名必須提交!", group = FirstGroup.class)
@Size(min = 2, max = 8, message = "用戶姓名的長度在2~8之間", goup = Second.class)
private String userName;
} @RestController
@RequestMapping("/user")
public class UserGroupSequenceController {
// 這里方法中@Validated注解value的值是Group.class
@PostMapping("/user")
public Result addGroup(@Validated(value = Group.class) @RequestBody UserGroupSequence user) {
return Result.buildSuccess(user);
}
}- 使用 @GroupSequence注解指定分組校驗順序后,第一組分組的約束的校驗沒有通過后,就不會進行第二組分組的約束的校驗
@Validated非實體類校驗
- 在非實體類上添加 @Validated注解對非實體類進行校驗
@Validated
public class AnnotationController {
@GetMapping("/person")
public Result getAge(@Range(min = 2, max = 8, message = "年齡在3~8歲!") @RequestParam int age) {
return Result.buildSuccess(age);
}
}- 在GlobalExceptionHandler中添加全局統(tǒng)一異常處理方法:
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
public Result resolveConstraintViolationException(ConstraintVilationException exception) {
Set<ConstraintVilation<?>> constraintVilations = exception.getConstraintVilations();
// 處理異常信息
if (!CollectionUtils.isEmpty(constraintVilations)) {
StringBuilder messageBuilder = new StringBuilder();
for (ConstraintVilation constraintViolation : constraintVilations) {
messageBuilder.append(constraintVilation.getMessage()).append(",");
}
String errorMessage = messageBuilder.toString();
if (errorMessage.length() > 1) {
errorMessage.substring(0, errorMessage.length() - 1);
}
return Result.builderFailure(ErrorStatus.ILLEGAL_DATA.getCode(), errorMessage);
}
return Result.builderFailure(ErrorStatus.ILLEGAL_DATA.getCode(), exception.getMessage())
}@PathVariable
- @PathVariable的作用: 用來指定請求URL路徑里面的變量
- @PathVariable和 @RequestParam的區(qū)別:
- @PathVariable用來指定請求URL中的變量
- @RequestParam用來獲取靜態(tài)的URL請求入?yún)?/li>
正則表達式校驗
- 使用正則表達式校驗 @PathVariable指定的路徑變量
// 請求路徑中的id必須是數(shù)字,否則尋找不到這個路徑404
@GetMapping("/user/{id:\\d+}")
public Result getId(@PathVariable(name="id") String userId) {
return Result.buildSuccess(userId);
}繼承BasicErrorController類
- @ControllerAdvice注解只能處理進入控制器方法拋出的異常
- BasicErrorController接口可以處理全局異常
- @PathVariable路徑校驗異常不是控制器方法拋出的,此時還沒有進入控制器方法:
- BasicErrorController處理異常,比如404異常時,會跳轉(zhuǎn)到 /error路徑,此時會返回錯誤的html頁面
- 為了保證返回結(jié)果統(tǒng)一,繼承BasicErrorController類,重寫BasicErrorController接口中的錯誤處理方法
@RestController
public class PathErrorController extends BasicErrorController {
@Autowired
public PathErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties, List<ErrorViewResolver> errorViewResolvers) {
super(errorAttributes, serverProperties.getError(), errorViewResolvers);
}
/**
* 處理html請求
*/
@Override
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = getStatus(request);
Map<String, Object> model = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
ModelAndView modelAndView = new ModelAndView("pathErrorPage", model, status);
return modelAndView;
}
/**
* 處理json請求
*/
@Override
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
Map<String, Object> responseBody = new HashMap<>(8);
responseBody.put("success", false);
responseBody.put("code", body.get("status"));
responseBody.put("message", body.get("error"));
return new ResponseEntity<>(responseBody, HttpStatus.OK);
}
} 自定義校驗注解
- 使用場景:
- 對某一個只能輸入指定值的字段進行校驗. 此時需要使用自定義注解實現(xiàn)
- 定義自定義的注解 @Show :
@Documented
@Constraint(validateBy = {Show.ShowConstraintValidator.class})
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Rentation(RUNTIME)
public @interface Show {
String message() default "{com.oxford.annotation.Show.message}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int[] value();
class ShowConstraintValidator implements ConstraintValidator<Show, Integer> {
private Set<Integer> set = new HashSet<>();
/**
* 初始化操作
* 獲取value屬性指定的數(shù)字,保存到Set集合中
*/
@Override
public void initilize(Show constraintAnnotation) {
int[] value = constraintAnnotation.value();
for (int v : value) {
set.add(i);
}
}
@Override
public boolean isValid(Integer value, ConstraintValidatorContext context) {
return set.contains(value);
}
}
}- 注意點:
- @Constraint注解:
- 將自定義的注解和實現(xiàn)的校驗類聯(lián)系起來
- 自定義校驗注解類需要實現(xiàn)ConstraintValidator<A extends Annotation, T> 接口
- 接口中第一個泛型參數(shù)表示的是自定義注解類
- 接口中第二個泛型參數(shù)表示的是校驗的屬性的值的類型
- initialize() 方法:
- 獲取到自定義注解中的相關(guān)的數(shù)據(jù)
- isValid() 方法:
- 實現(xiàn)自定義的校驗邏輯
- 返回boolean類型的校驗結(jié)果
- @Constraint注解:
- 自定義注解的使用:
@Data
public class AnnotationQuery {
@Show(value = {0, 1}, message = "數(shù)值只能是0或者1")
private Integer isShow;
}@PostMapping("/annotation")
public Result addAnnotation(@Validated @RequestBody AnnotationQuery annotation) {
return Result.buildSuccess(annotation);
}到此這篇關(guān)于Java中的三種校驗注解的使用(@Valid,@Validated和@PathVariable)的文章就介紹到這了,更多相關(guān)Java 校驗注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:
- 使用@Validated和@Valid 解決list校驗的問題
- spring @Validated 注解開發(fā)中使用group分組校驗的實現(xiàn)
- Java參數(shù)校驗@Validated、@Valid介紹及使用詳解
- SpringBoot參數(shù)校驗之@Validated的使用詳解
- @Valid和@Validated注解校驗以及異常處理方式
- 使用@Validated注解進行校驗卻沒有效果的解決
- Spring 中@Validated 分組校驗的使用解析
- Spring利用@Validated注解實現(xiàn)參數(shù)校驗詳解
- JAVA校驗之@Valid和@Validated實踐指南
相關(guān)文章
Eclipse下使用ANT編譯提示OutOfMemory的解決方法
由于需要使用ANT編譯的代碼比較多,特別是在第一次變異的時候,會出現(xiàn)OutOfMemory錯誤。并提示更改ANT_OPTS設(shè)定。2009-04-04
JPA中@CreatedDate和@LastModifiedDate的使用方式
這篇文章主要介紹了JPA中@CreatedDate和@LastModifiedDate的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-11-11

