<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # validation ## 基本使用 JSR實現,一個規范文檔,指定一整套API,通過標注給對象屬性添加約束. Hibernate Validator提供了JSR規范所有內置約束注解實現,以及一些附加的約束注解,用戶還可以自定義注解. * @Valid參數前面添加@Valid注解,代表此對象使用了參數校驗 * BindingResult參數校驗的結果會存儲在此對象中,可以根據屬性判斷是否校驗通過,校驗不通過可以把錯誤信息打印出來 1. 參數user前需要加上@Validated注解,表明需要spring對其進行校驗,而校驗的信息會存放到其后的BindingResult中。注意,必須相鄰,如果有多個參數需要校驗,形式可以如下。 ~~~ foo(@Validated Foo foo, BindingResult fooBindingResult ,@Validated Bar bar, BindingResult barBindingResult); ~~~ 即一個校驗類對應一個校驗結果。 2. 校驗結果會被自動填充,在controller中可以根據業務邏輯來決定具體的操作,如跳轉到錯誤頁面 ~~~ import org.springframework.validation.BindingResult; import org.springframework.validation.ObjectError; @RequestMapping("/saveUser") public void saveUser(@Valid User user, BindingResult result) { System.out.println("user:" + user); if (result.hasErrors()) { List<ObjectError> list = result.getAllErrors(); for (ObjectError error : list) { System.out.println(error.getCode() + "-" + error.getDefaultMessage()); } } } ~~~ 需要定義一個接受的數據類型 其中, message="密碼不不能為空"是自定義錯誤類型 ~~~ import lombok.Data; import org.hibernate.validator.constraints.Length; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotEmpty; @Data public class User { @NotEmpty(message = "姓名不能為空") private String name; @Max(value = 100, message = "年齡不能大于100歲") @Min(value = 18, message = "必須年滿18歲") private int age; @NotEmpty(message = "密碼不能為空") @Length(min = 6, message = "密碼長度不能小于6位") private String pass; } ~~~ 測試 ~~~ String responseString = mockMvc.perform(MockMvcRequestBuilders.post("/saveUser") .param("name", "") .param("age", "666") .param("pass", "test") ).andReturn().getResponse().getContentAsString(); System.out.println(responseString); ~~~ ~~~ user:name=,age=666,pass=test Max-年年齡不不能?大于100歲 Length-密碼?長度不不能?小于6位 NotEmpty-姓名不不能為空 ~~~ ## 部分標簽含義 | 限制 | 說明 | | --- | --- | | @Valid | 被注釋的元素是一個對象,需要檢查此對象的所有字段值 | | @Null | 被注釋的元素必須為 null | | @NotNull | 被注釋的元素必須不為 null | | @AssertTrue | 被注釋的元素必須為 true | | @AssertFalse | 被注釋的元素必須為 false | | @Min(value) | 被注釋的元素必須是一個數字,其值必須大于等于指定的最小值 | | @Max(value) | 被注釋的元素必須是一個數字,其值必須小于等于指定的最大值 | | @DecimalMin(value) | 被注釋的元素必須是一個數字,其值必須大于等于指定的最小值 | | @DecimalMax(value) | 被注釋的元素必須是一個數字,其值必須小于等于指定的最大值 | | @Size(max, min) | 被注釋的元素的大小必須在指定的范圍內 | | @Digits (integer, fraction) | 被注釋的元素必須是一個數字,其值必須在可接受的范圍內 | | @Past | 被注釋的元素必須是一個過去的日期 | | @Future | 被注釋的元素必須是一個將來的日期 | | @Pattern(value) | 被注釋的元素必須符合指定的正則表達式 | | @Email | 被注釋的元素必須是電子郵箱地址 | | @Length(min, max) | 被注釋的字符串的大小必須在指定的范圍內 | | @NotEmpty | 被注釋的字符串的大小必須在指定的范圍內 | | @Range(min, max) | 被注釋的元素必須在合適的范圍內 | | @NotBlank | 被注釋的字符串的必須非空 | | @URL(protocol, host, port, regexp, flags) | 被注釋個 的字符串必須是一個有效的url | | @CreditCardNumber | 被注釋的字符串必須通過Luhn校驗算法,銀行卡,信用卡等號碼一般都用Luhn計算合法性 | | @ScriptAssert(lang, script, alias) | 要有Java Scripting API 即JSR 223 ("Scripting for the JavaTM Platform")的實現 | | @SafeHtml(whitelistType, additionalTags) | classpath中要有jsoup包 | ~~~ @Pattern(regexp="^[a-zA-Z0-9]+$",message="{account.username.space}") @Size(min=3,max=20,message="{account.username.size}") ~~~ # 自定義校驗 校驗手機號或身份證號,官方提供的注解中沒有支持的,當然我們可以通過官方提供的正則表達式來校驗: ~~~ @Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手機號碼格式錯誤") @NotBlank(message = "手機號碼不能為空") private String phone; ~~~ **定義手機號校驗注解 @Phone** ~~~ @Target({ ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = PhoneValidator.class) public @interface Phone { /** * 校驗不通過的message */ String message() default "請輸入正確的手機號"; /** * 分組校驗 */ Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; } ~~~ **定義校驗方式** 想讓自定義驗證注解生效,需要實現`ConstraintValidator`接口。 接口的第一個參數是 **自定義注解類型**,第二個參數是**被注解字段的類型** 需要提到的一點是`ConstraintValidator`接口的實現類無需添加`@Component`它在啟動的時候就已經被加載到容器中了 ~~~ public class PhoneValidator implements ConstraintValidator<Phone, String> { @Override public void initialize(Phone constraintAnnotation) { } @Override public boolean isValid(String phone, ConstraintValidatorContext constraintValidatorContext) { if(!StringUtils.isEmpty(phone)){ //獲取默認提示信息 String defaultConstraintMessageTemplate = constraintValidatorContext.getDefaultConstraintMessageTemplate(); System.out.println("default message :" + defaultConstraintMessageTemplate); //禁用默認提示信息 constraintValidatorContext.disableDefaultConstraintViolation(); //設置提示語 constraintValidatorContext.buildConstraintViolationWithTemplate("手機號格式錯誤").addConstraintViolation(); String regex = "^1(3|4|5|7|8)\\d{9}$"; return phone.matches(regex); } return true; } } ~~~ # 分組校驗 當發生多個錯誤,spring validation不會在第一個錯誤發生后立即停止,而是繼續試錯,告訴我們所有的錯誤。 如果同一個類,在不同的使用場景下有不同的校驗規則,那么可以使用分組校驗。未成年人是不能喝酒的,而在其他場景下我們不做特殊的限制,這個需求如何體現同一個實體,不同的校驗規則呢? 改寫注解,添加分組: ~~~ Class Foo{ @Min(value = 18,groups = {Adult.class}) private Integer age; public interface Adult{} public interface Minor{} } ~~~ 這樣表明,只有在Adult分組下,18歲的限制才會起作用。 Controller層改寫: drink方法限定需要進行Adult校驗,而live方法則不做限制。 ~~~ @RequestMapping("/drink") public String drink(@Validated({Foo.Adult.class}) Foo foo, BindingResult bindingResult) { if(bindingResult.hasErrors()){ for (FieldError fieldError : bindingResult.getFieldErrors()) { //... } return "fail"; } return "success"; } @RequestMapping("/live") public String live(@Validated Foo foo, BindingResult bindingResult) { if(bindingResult.hasErrors()){ for (FieldError fieldError : bindingResult.getFieldErrors()) { //... } return "fail"; } return "success"; } ~~~ # 統一錯誤信息 定義錯誤信息 在resources/下創建名稱為ValidationMessages.properties 注意:名字必須為“ValidationMessages.properties“ 因為SpringBoot自動讀取classpath中的ValidationMessages.properties里的錯誤信息 value 為提示信息 ,但是是ASCII 。(內容為“名字不能為空“) ~~~ # 中文是不行的 member.mid.notnull.error=用戶名不允許為空 member.mid.email.error=用戶名的注冊必須輸入正確的郵箱 member.mid.length.error=用戶名的格式錯誤 ~~~ ![](https://img.kancloud.cn/79/34/7934b50c613cb4413e6e4bcbf6397d6f_1456x72.png) ~~~ @NotNull(message="{member.mid.notnull.error}") @Email(message="{member.mid.email.error}") @Length(min=6,message="{member.mid.length.error}") private String mid; ~~~ ## 自定義異常處理器 當驗證不通過時會拋異常出來,在全局異常中定義異常處理器。 捕獲異常信息(因為驗證不通過的項可能是多個所以統一捕獲處理),并拋給前端。 ![](https://img.kancloud.cn/4b/cd/4bcdbf55a24a9ce7d6c2263190ecd4d5_1694x240.png) @RestControllerAdvice @ExceptionHandler(寫你想要攔截的異常類型) **這兩個注解必須要** 第一個方法是校驗異常的統一處理 第二個是防止參數類型不一致的處理 當然你也可以在里面處理其他異常。 ~~~ @RestControllerAdvice public class BadRequestExceptionHandler { private static final Logger logger = LoggerFactory.getLogger(BadRequestExceptionHandler.class); /** * 校驗錯誤攔截處理 * * @param exception 錯誤信息集合 * @return 錯誤信息 */ @ExceptionHandler(MethodArgumentNotValidException.class) public ServiceResult validationBodyException(MethodArgumentNotValidException exception){ BindingResult result = exception.getBindingResult(); if (result.hasErrors()) { List<ObjectError> errors = result.getAllErrors(); errors.forEach(p ->{ FieldError fieldError = (FieldError) p; logger.error("Data check failure : object{"+fieldError.getObjectName()+"},field{"+fieldError.getField()+ "},errorMessage{"+fieldError.getDefaultMessage()+"}"); }); } return ServiceResult.error("請填寫正確信息"); } /** * 參數類型轉換錯誤 * * @param exception 錯誤 * @return 錯誤信息 */ @ExceptionHandler(HttpMessageConversionException.class) public ServiceResult parameterTypeException(HttpMessageConversionException exception){ logger.error(exception.getCause().getLocalizedMessage()); return ServiceResult.error("類型轉換錯誤"); } } ~~~ # @Validated和@Valid的區別 * @Valid是使用Hibernate validation的時候使用 * @Validated是只用Spring Validator校驗機制使用 說明:java的JSR303聲明了@Valid這類接口,而`Hibernate-validator`對其進行了實現 @Validation對@Valid進行了二次封裝,在使用上并沒有區別,但在分組、注解位置、嵌套驗證等功能上有所不同,這里主要就這幾種情況進行說明。 **注解位置** * @Validated:用在類型、方法和方法參數上。但不能用于成員屬性(field) * @Valid:可以用在方法、構造函數、方法參數和成員屬性(field)上 **分組校驗** * @Validated:提供分組功能,可以在參數驗證時,根據不同的分組采用不同的驗證機制 * @Valid:沒有分組功能 舉例: 定義分組接口: ~~~ public interface IGroupA {} public interface IGroupB {} ~~~ 定義需要檢驗的參數bean: ~~~ public class StudentBean implements Serializable{ @NotBlank(message = "用戶名不能為空") private String name; //只在分組為IGroupB的情況下進行驗證 @Min(value = 18, message = "年齡不能小于18歲", groups = {IGroupB.class}) private Integer age; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機號格式錯誤") private String phoneNum; @Email(message = "郵箱格式錯誤") private String email; @MyConstraint private String className; ~~~ 測試代碼: 檢驗分組為IGroupA的情況 ~~~ @RestController public class CheckController { @PostMapping("stu") public String addStu(@Validated({IGroupA.class}) @RequestBody StudentBean studentBean){ return "add student success"; } } ~~~ 這里對分組IGroupB的就沒檢驗了 如果把測試代碼改成下面這樣,看看測試結果 ~~~ @RestController public class CheckController { @PostMapping("stu") public String addStu(@Validated({IGroupA.class, IGroupB.class}) @RequestBody StudentBean studentBean){ return "add student success"; } } ~~~ 說明: 1. 不分 配groups,默認每次都要進行驗證 2. 對一個參數需要多種驗證方式時,也可通過分配不同的組達到目的。 # 組序列 默認情況下 不同級別的約束驗證是無序的,但是在一些情況下,順序驗證卻是很重要。 一個組可以定義為其他組的序列,使用它進行驗證的時候必須符合該序列規定的順序。在使用組序列驗證的時候,如果序列前邊的組驗證失敗,則后面的組將不再給予驗證。 **定義組序列** ~~~ @GroupSequence({Default.class, IGroupA.class, IGroupB.class}) public interface IGroup { } ~~~ 需要校驗的Bean,分別定義IGroupA對age進行校驗,IGroupB對className進行校驗: ~~~ public class StudentBean implements Serializable{ @NotBlank(message = "用戶名不能為空") private String name; @Min(value = 18, message = "年齡不能小于18歲", groups = IGroupA.class) private Integer age; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機號格式錯誤") private String phoneNum; @Email(message = "郵箱格式錯誤") private String email; @MyConstraint(groups = IGroupB.class) private String className; ~~~ 測試代碼 ~~~ @RestController public class CheckController { @PostMapping("stu") public String addStu(@Validated({IGroup.class}) @RequestBody StudentBean studentBean){ return "add student success"; } } ~~~ 測試發現,如果age出錯,那么對組序列在IGroupA后的IGroupB不進行校驗,即例子中的className不進行校驗 # 嵌套校驗 一個待驗證的pojo類,其中還包含了待驗證的對象,需要在待驗證對象上注解@Valid,才能驗證待驗證對象中的成員屬性,這里不能使用@Validated。 需要約束校驗的bean: ~~~ public class TeacherBean { @NotEmpty(message = "老師姓名不能為空") private String teacherName; @Min(value = 1, message = "學科類型從1開始計算") private int type; ~~~ ~~~ public class StudentBean implements Serializable{ @NotBlank(message = "用戶名不能為空") private String name; @Min(value = 18, message = "年齡不能小于18歲") private Integer age; @Pattern(regexp = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手機號格式錯誤") private String phoneNum; @Email(message = "郵箱格式錯誤") private String email; @MyConstraint private String className; @Valid @NotNull(message = "任課老師不能為空") @Size(min = 1, message = "至少有一個老師") private List<TeacherBean> teacherBeans; ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看