Java中JSR303的基本使用詳情
1.關(guān)于JSR-303
JSR-303規(guī)范(Bean Validation規(guī)范)提供了對 Java EE 和 Java SE 中的 Java Bean 進行驗證的方式。該規(guī)范主要使用注解的方式來實現(xiàn)對 Java Bean 的驗證功能 。
Hibernate Validator 提供了 JSR 303 規(guī)范中所有內(nèi)置 constraint 的實現(xiàn),除此之外還有一些附加的 constraint。官方文檔
Bean Validation 中內(nèi)置的 constraint:
約束注解名稱 | ** 約束注解說明** |
---|---|
@Null | 驗證對象是否為空 |
@NotNull | 驗證對象是否為非空 |
@AssertTrue | 驗證 Boolean 對象是否為 true |
@AssertFalse | 驗證 Boolean 對象是否為 false |
@Min | 驗證 Number 和 String 對象是否大等于指定的值 |
@Max | 驗證 Number 和 String 對象是否小等于指定的值 |
@DecimalMin | 驗證 Number 和 String 對象是否大等于指定的值,小數(shù)存在精度 |
@DecimalMax | 驗證 Number 和 String 對象是否小等于指定的值,小數(shù)存在精度 |
@Size | 驗證對象(Array,Collection,Map,String)長度是否在給定的范圍之內(nèi) |
@Digits | 驗證 Number 和 String 的構(gòu)成是否合法 |
@Past | 驗證 Date 和 Calendar 對象是否在當前時間之前 |
@Future | 驗證 Date 和 Calendar 對象是否在當前時間之后 |
@Pattern | 驗證 String 對象是否符合正則表達式的規(guī)則 |
2. 基本使用
- 在參數(shù)上加上校驗注解,如果參數(shù)是自定義類型,則在類的屬性上加校驗注解。
- 使校驗注解生效
- 2.1 直接在參數(shù)上加校驗注解,需要在類上加
@Validated
- 2.1 自定義類型,變量前面加
@Validated
或者@Valid
- 2.1 直接在參數(shù)上加校驗注解,需要在類上加
@Data public class Emp { //不能為空且不能為空串 @NotBlank(message = "賬號不能為空") private String username; } @PostMapping("/emp/add") public Result demo1(@Valid Emp emp,@NotBlank String email){ return Result.success(200,"成功"); }
@Validated和@Valid的區(qū)別
@Validated:
Spring提供的支持分組校驗可以用在類型、方法和方法參數(shù)上。但是不能用在成員屬性(字段)上由于無法加在成員屬性(字段)上,所以無法單獨完成級聯(lián)校驗,需要配合@Valid
@Valid:
JDK提供的(標準JSR-303規(guī)范)不支持分組校驗可以用在方法、構(gòu)造函數(shù)、方法參數(shù)和成員屬性(字段)上可以加在成員屬性(字段)上,能夠獨自完成級聯(lián)校驗
3. 級聯(lián)驗證
一個待驗證的pojo類,其中又包含了一個待驗證的對象。
@Data public class Emp implements Serializable { //不能為空且不能為空串(調(diào)用trim()后) @NotBlank(message = "賬號不能為空") private String username; @Valid //需要加上,否則不會驗證Dept類中的校驗注解 @NotNull //并且需要觸發(fā)該字段的驗證才會進行嵌套驗證。 private Dept dept; } @Data public class Dept implements Serializable { @NotBlank(message = "deptNameb不能為空") private String deptName; }
4. 分組驗證
驗證時只對特定的屬性進行校驗,不知道默認為Default
4.1定義接口,充當標識
public interface IGroup { interface Registry extends Default {} interface Update extends Default {} }
4.2 指定校驗的組
@Data public class Emp implements Serializable { //當校驗的組為update時才校驗該字段 @NotNull(message = "編號不能為空",groups = {IGroup.Update.class}) @Min(value = 1,groups = {IGroup.Update.class}) private Integer empNo; //不能為空且不能為空串(調(diào)用trim()后) @NotBlank(message = "賬號不能為空") private String username; @Pattern(regexp = "^[0-9A-z]{10,18}$",message = "密碼只能使用數(shù)字+字母",groups = IGroup.Registry.class) private String password; @Valid @NotNull private Dept dept; }
@PostMapping("/emp/add") //指定需要校驗的組 public Result addEmp(@RequestBody @Validated(IGroup.Registry.class) Emp emp){ return Result.success(200,"成功"); }
5. 組序列
指定組與組之間的檢驗順序,如果第一個組校驗沒過,就不會校驗后面的組
@GroupSequence({Default.class,IGroup.Update.class, IGroup.Registry.class}) public interface IGroup { interface Registry extends Default {} interface Update extends Default {} }
@PostMapping("/emp/add") public Result addEmp(@RequestBody @Validated({IGroup.class}) Emp emp){ return Result.success(200,"成功"); }
隨便定義一個接口然后在接口上使用@GroupSequence就行。
還有一個注解是@GroupSequenceProvider,使用這個注解需要實現(xiàn)DefaultGroupSequenceProvider接口,重寫里面getValidationGroups方法,然后根據(jù)情況動態(tài)的添加需要需要校驗的分組。
6. 自定義校驗注解
按照官網(wǎng)的示例
檢查當前字符串是否為全大寫,或者全小寫
定義模型:
public interface CaseMode{ String UPPER="大寫"; String LOWER="小寫"; }
創(chuàng)建自定義注解:
@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE, TYPE_USE }) @Retention(RUNTIME) @Constraint(validatedBy = CheckCaseValidator.class) //指定自定義驗證器 @Documented @Repeatable(CheckCase.List.class) //表示可以在同一位置重復多次 public @interface CheckCase { //默認的錯誤信息 String message() default "{verification.default.Errormessage}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; String value(); @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE }) @Retention(RUNTIME) @Documented @interface List { CheckCase[] value(); } }
創(chuàng)建自定義驗證器,第一個泛型是自定義注解、第二個是校驗值的類型,也就是注解標注的字段的類型
public class CheckCaseValidator implements ConstraintValidator<CheckCase, String> { private String caseMode; @Override public void initialize(CheckCase constraintAnnotation) { this.caseMode = constraintAnnotation.value(); } /** * 判斷是否通過校驗 * @param value 傳入的值 * @param context * @return */ @Override public boolean isValid(String value, ConstraintValidatorContext context) { if ( value == null ) { return true; } if (CaseMode.UPPER.equals(caseMode) ) { return value.equals( value.toUpperCase() ); } else { return value.equals( value.toLowerCase() ); } } }
在 resources
目錄下創(chuàng)建一個 ValidationMessages.properties
配置文件,key
是第二步 message
設(shè)置的默認值,value
是自定義錯誤信息。{value}為 @CheckCase的value屬性的值
verification.default.Errormessage=字母必須為全為{value}
7. 校驗結(jié)果的處理
7.1 全局異常處理
@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(BindException.class) public HashMap<String, String> bindExceptionHandler(BindException e){ HashMap<String, String> map = new HashMap<>(); e.getBindingResult().getFieldErrors().forEach(field -> { map.put(field.getField(), field.getDefaultMessage()); }); return map; } @ExceptionHandler(MethodArgumentNotValidException.class) public HashMap<String, String> methodArgumentNotValidException(MethodArgumentNotValidException e){ HashMap<String, String> map = new HashMap<>(); e.getBindingResult().getFieldErrors().forEach(field -> { map.put(field.getField(), field.getDefaultMessage()); }); return map; } @ExceptionHandler(ConstraintViolationException.class) public HashMap<String, String> handle(ConstraintViolationException e) { HashMap<String, String> map = new HashMap<>(); e.getConstraintViolations().forEach(item->{ map.put(item.getPropertyPath().toString(),item.getMessage()); }); return map; } }
7.2 BindRequest
@PostMapping("/emp/test") public Result test(@Validated Emp emp, BindingResult validResult){ if (validResult.hasErrors()){ HashMap<String, String> map = new HashMap<>(); validResult.getFieldErrors().forEach(error->{ map.put(error.getField(),error.getDefaultMessage()); }); return Result.error(HttpStatus.BAD_REQUEST.value(),map); } return Result.success(HttpStatus.OK.value(),"成功"); }
7.3 Validator
@SpringBootTest public class ValidatorTest { private static Validator validator = Validation.byProvider(HibernateValidator.class) .configure() .failFast(false) // 是否開啟快速失敗模式 .buildValidatorFactory() .getValidator(); @Test public void test1(){ Emp emp = new Emp(); //單獨校驗某個屬性 //Set<ConstraintViolation<Emp>> validProperty = validator.validateProperty(emp, "username"); //檢驗對象 Set<ConstraintViolation<Emp>> validBean = validator.validate(emp); Iterator<ConstraintViolation<Emp>> iterator = validBean.iterator(); while (iterator.hasNext()){ ConstraintViolation<Emp> next = iterator.next(); String property = next.getPropertyPath().toString(); String message = next.getMessage(); System.out.println(property+":"+message); } } }
到此這篇關(guān)于Java中JSR303的基本使用詳情的文章就介紹到這了,更多相關(guān)Java JSR303內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot整合Quartz實現(xiàn)定時任務詳解
這篇文章主要介紹了Java?任務調(diào)度框架?Quartz,Quartz是OpenSymphony開源組織在Job?scheduling領(lǐng)域又一個開源項目,完全由Java開發(fā),可以用來執(zhí)行定時任務,類似于java.util.Timer。,下面我們來學習一下關(guān)于?Quartz更多的詳細內(nèi)容,需要的朋友可以參考一下2022-08-08Map按單個或多個Value排序當Value相同時按Key排序
Map可以先按照value進行排序,然后按照key進行排序。 或者先按照key進行排序,然后按照value進行排序,這樣操作都行,這篇文章主要介紹了Map按單個或多個Value排序,當Value相同時按Key排序,需要的朋友可以參考下2023-02-02SpringBoot 簽到獎勵實現(xiàn)方案的示例代碼
這篇文章主要介紹了SpringBoot 簽到獎勵實現(xiàn)方案的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-08-08IntelliJ IDEA的數(shù)據(jù)庫管理工具實在太方便了(推薦)
這篇文章主要介紹了IntelliJ IDEA的數(shù)據(jù)庫管理工具實在太方便了,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09