您好,登錄后才能下訂單哦!
這篇文章主要介紹“Java中的@Valid,@Validated和@PathVariable怎么用”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Java中的@Valid,@Validated和@PathVariable怎么用”文章能幫助大家解決問題。
相同點:
@Valid注解和 @Validated注解都是開啟校驗功能的注解
不同點:
@Valid注解 : 可以使用在方法,構造函數,方法參數和成員屬性上
@Validated注解 : 可以用在類型,方法和方法參數上. 但是不能用在成員屬性上
@Validated注解是Spring基于 @Valid注解的進一步封裝,并提供比如分組,分組順序的高級功能
使用位置不同:
級聯校驗: 也叫嵌套檢測.嵌套就是一個實體類包含另一個實體類
@Valid和可以用在成員屬性的字段上,因此 @Valid可以提供級聯校驗
示例:
@Data public class Hair { @NotBlank(message = "頭發長度必須提交!") private Double length; @NotBlank(message = "頭發顏色必須提交!") private String color; } @Data public class Person { @NotBlank(message = "用戶姓名必須提交!") @Size(min=2, max=8) private String userName; // 添加@Valid注解實現嵌套檢測 @Valid @NotEmpty(message = "用戶要有頭發!") private List<Hair> hairs; } @PostMapping("/person") public Result addPerson(@Valid @RequestBody Person person) { return Result.buildSuccess(person); }
只是在方法參數前面添加 @Valid和 @Validated注解,不會對嵌套的實體類進行校驗.要想實現對嵌套的實體類進行校驗,需要在嵌套的實體類屬性上添加 @Valid注解
分組校驗:
對指定的組開啟校驗,可以分別作用于不同的業務場景中
分組校驗是由 @Validated注解中的value提供的
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; }
JSR 303校驗注解中的分組方法groups
示例:
開啟分組校驗: 通過 @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的值指定這個分組時,開會開啟注解的校驗數據的功能
默認情況下,分組間的約束是無序的,但是在一些特殊的情況下可能對分組間的校驗有一定的順序
比如第二組的分組的約束的校驗需要依賴第一組的穩定狀態來進行,此時,要求分組間的約束校驗一定要有順序
分組校驗順序通過使用 @GroupSequence注解實現
示例:
@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 public class AnnotationController { @GetMapping("/person") public Result getAge(@Range(min = 2, max = 8, message = "年齡在3~8歲!") @RequestParam int age) { return Result.buildSuccess(age); } }
在GlobalExceptionHandler中添加全局統一異常處理方法:
@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的作用: 用來指定請求URL路徑里面的變量
@PathVariable和 @RequestParam的區別:
@PathVariable用來指定請求URL中的變量
@RequestParam用來獲取靜態的URL請求入參
使用正則表達式校驗 @PathVariable指定的路徑變量
// 請求路徑中的id必須是數字,否則尋找不到這個路徑404 @GetMapping("/user/{id:\\d+}") public Result getId(@PathVariable(name="id") String userId) { return Result.buildSuccess(userId); }
@ControllerAdvice注解只能處理進入控制器方法拋出的異常
BasicErrorController接口可以處理全局異常
@PathVariable路徑校驗異常不是控制器方法拋出的,此時還沒有進入控制器方法:
BasicErrorController處理異常,比如404異常時,會跳轉到 /error路徑,此時會返回錯誤的html頁面
為了保證返回結果統一,繼承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); } }
使用場景:
對某一個只能輸入指定值的字段進行校驗. 此時需要使用自定義注解實現
定義自定義的注解 @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屬性指定的數字,保存到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); } } }
注意點:
實現自定義的校驗邏輯
返回boolean類型的校驗結果
獲取到自定義注解中的相關的數據
接口中第一個泛型參數表示的是自定義注解類
接口中第二個泛型參數表示的是校驗的屬性的值的類型
將自定義的注解和實現的校驗類聯系起來
@Constraint注解:
自定義校驗注解類需要實現ConstraintValidator<A extends Annotation, T> 接口
initialize() 方法:
isValid() 方法:
自定義注解的使用:
@Data public class AnnotationQuery { @Show(value = {0, 1}, message = "數值只能是0或者1") private Integer isShow; }
@PostMapping("/annotation") public Result addAnnotation(@Validated @RequestBody AnnotationQuery annotation) { return Result.buildSuccess(annotation); }
關于“Java中的@Valid,@Validated和@PathVariable怎么用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。