<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringCloud里參數(shù)校驗/參數(shù)驗證

          共 5148字,需瀏覽 11分鐘

           ·

          2020-10-07 17:00

          點擊上方藍色字體,選擇“標星公眾號”

          優(yōu)質(zhì)文章,第一時間送達

          66套java從入門到精通實戰(zhàn)課程分享

          1、前言

          在控制器類的方法里自己寫校驗邏輯代碼當然也可以,只是代碼比較丑陋,有點“l(fā)ow”。業(yè)界有更好的處理方法,分別闡述如下。

          2、PathVariable校驗

          @GetMapping("/path/{group:[a-zA-Z0-9_]+}/{userid}")
          @ResponseBody
          public?String?path(@PathVariable("group")?String?group,?@PathVariable("userid")?Integer?userid)?{
          ????return?group?+?":"?+?userid;
          }

          用法是:路徑變量:正則表達式。當請求URI不滿足正則表達式時,客戶端將收到404錯誤碼。不方便的地方是,不能通過捕獲異常的方式,向前端返回統(tǒng)一的、自定義格式的響應參數(shù)。

          3、方法參數(shù)校驗

          @GetMapping("/validate1")
          @ResponseBody
          public?String?validate1(
          ????????@Size(min?=?1,max?=?10,message?=?"姓名長度必須為1到10")@RequestParam("name")?String?name,
          ????????@Min(value?=?10,message?=?"年齡最小為10")@Max(value?=?100,message?=?"年齡最大為100")?@RequestParam("age")?Integer?age)?{
          ????return?"validate1";
          }


          如果前端傳遞的參數(shù)不滿足規(guī)則,則拋出異常。注解Size、Min、Max來自validation-api.jar,更多注解參見相關標準小節(jié)。

          4、表單對象/VO對象校驗

          當參數(shù)是VO時,可以在VO類的屬性上添加校驗注解。

          public?class?User?{
          ????@Size(min?=?1,max?=?10,message?=?"姓名長度必須為1到10")
          ????private?String?name;
          ?
          ????@NotEmpty
          ????private?String?firstName;
          ?
          ????@Min(value?=?10,message?=?"年齡最小為10")@Max(value?=?100,message?=?"年齡最大為100")
          ????private?Integer?age;
          ?
          ????@Future
          ????@JSONField(format="yyyy-MM-dd?HH:mm:ss")
          ????private?Date?birth;
          ????。。。
          }


          其中,F(xiàn)uture注解要求必須是相對當前時間來講“未來的”某個時間。

          @PostMapping("/validate2")
          @ResponseBody
          public?User?validate2(@Valid?@RequestBody?User?user){
          ????return?user;
          }

          5、自定義校驗規(guī)則

          5.1 自定義注解校驗

          需要自定義一個注解類和一個校驗類。

          import?javax.validation.Constraint;
          import?javax.validation.Payload;
          import?java.lang.annotation.*;
          ?
          @Documented
          @Retention(RetentionPolicy.RUNTIME)
          @Target({ElementType.PARAMETER,ElementType.FIELD})
          @Constraint(validatedBy?=?FlagValidatorClass.class)
          public?@interface?FlagValidator?{
          ????//?flag的有效值,多個使用,隔開
          ????String?values();
          ?
          ????//?flag無效時的提示內(nèi)容
          ????String?message()?default?"flag必須是預定義的那幾個值,不能隨便寫";
          ?
          ????Class[]?groups()?default?{};
          ?
          ????Class[]?payload()?default?{};
          }


          import?javax.validation.ConstraintValidator;
          import?javax.validation.ConstraintValidatorContext;
          ?
          public?class?FlagValidatorClass?implements?ConstraintValidator?{
          ????/**
          ?????*?FlagValidator注解規(guī)定的那些有效值
          ?????*/
          ????private?String?values;
          ?
          ????@Override
          ????public?void?initialize(FlagValidator?flagValidator)?{
          ????????this.values?=?flagValidator.values();
          ????}
          ?
          ????/**
          ?????*?用戶輸入的值,必須是FlagValidator注解規(guī)定的那些值其中之一。
          ?????*?否則,校驗不通過。
          ?????*?@param?value?用戶輸入的值,如從前端傳入的某個值
          ?????*/
          ????@Override
          ????public?boolean?isValid(Object?value,?ConstraintValidatorContext?constraintValidatorContext)?{
          ????????//?切割獲取值
          ????????String[]?value_array?=?values.split(",");
          ????????Boolean?isFlag?=?false;
          ?
          ????????for?(int?i?=?0;?i?????????????//?存在一致就跳出循環(huán)
          ????????????if?(value_array[i]?.equals(value)){
          ????????????????isFlag?=?true;?break;
          ????????????}
          ????????}
          ?
          ????????return?isFlag;
          ????}
          }


          使用我們自定義的注解:

          public?class?User?{
          ????//?前端傳入的flag值必須是1或2或3,否則校驗失敗
          ????@FlagValidator(values?=?"1,2,3")
          ????private?String?flag?;
          ????。。。
          }

          5.2 分組校驗

          import?org.hibernate.validator.constraints.Length;
          import?javax.validation.constraints.Min;
          import?javax.validation.constraints.NotNull;
          ?
          public?class?Resume?{
          ????public?interface?Default?{
          ????}
          ?
          ????public?interface?Update?{
          ????}
          ?
          ????@NotNull(message?=?"id不能為空",?groups?=?Update.class)
          ????private?Long?id;
          ?
          ????@NotNull(message?=?"名字不能為空",?groups?=?Default.class)
          ????@Length(min?=?4,?max?=?10,?message?=?"name?長度必須在?{min}?-?{max}?之間",?groups?=?Default.class)
          ????private?String?name;
          ?
          ????@NotNull(message?=?"年齡不能為空",?groups?=?Default.class)
          ????@Min(value?=?18,?message?=?"年齡不能小于18歲",?groups?=?Default.class)
          ????private?Integer?age;
          ????。。。
          }


          ????/**
          ?????*?使用Defaul分組進行驗證
          ?????*?@param?resume
          ?????*?@return
          ?????*/
          ????@PostMapping("/validate5")
          ????public?String?addUser(@Validated(value?=?Resume.Default.class)?@RequestBody?Resume?resume)?{
          ????????return?"validate5";
          ????}
          ?
          ????/**
          ?????*?使用Default、Update分組進行驗證
          ?????*?@param?resume
          ?????*?@return
          ?????*/
          ????@PutMapping("/validate6")
          ????public?String?updateUser(@Validated(value?=?{Resume.Update.class,?Resume.Default.class})?@RequestBody?Resume?resume)?{
          ????????return?"validate6";
          ????}


          建立了兩個分組,名稱分別為Default、Update。POST方法提交時使用Defaut分組的校驗規(guī)則,PUT方法提交時同時使用兩個分組規(guī)則。

          6、異常攔截器

          通過設置全局異常處理器,統(tǒng)一向前端返回校驗失敗信息。

          import?com.scj.springbootdemo.WebResult;
          import?org.slf4j.Logger;
          import?org.slf4j.LoggerFactory;
          import?org.springframework.util.CollectionUtils;
          import?org.springframework.validation.ObjectError;
          import?org.springframework.web.bind.MethodArgumentNotValidException;
          import?org.springframework.web.bind.annotation.ControllerAdvice;
          import?org.springframework.web.bind.annotation.ExceptionHandler;
          import?org.springframework.web.bind.annotation.ResponseBody;
          ?
          import?javax.validation.ConstraintViolation;
          import?javax.validation.ConstraintViolationException;
          import?java.util.List;
          import?java.util.Set;
          ?
          /**
          ?*?全局異常處理器
          ?*/
          @ControllerAdvice
          public?class?GlobalExceptionHandler?{
          ?
          ????private?Logger?logger?=?LoggerFactory.getLogger(GlobalExceptionHandler.class);
          ?
          ????/**
          ?????*?用來處理bean?validation異常
          ?????*?@param?ex
          ?????*?@return
          ?????*/
          ????@ExceptionHandler(ConstraintViolationException.class)
          ????@ResponseBody
          ????public??WebResult?resolveConstraintViolationException(ConstraintViolationException?ex){
          ????????WebResult?errorWebResult?=?new?WebResult(WebResult.FAILED);
          ????????Set>?constraintViolations?=?ex.getConstraintViolations();
          ????????if(!CollectionUtils.isEmpty(constraintViolations)){
          ????????????StringBuilder?msgBuilder?=?new?StringBuilder();
          ????????????for(ConstraintViolation?constraintViolation?:constraintViolations){
          ????????????????msgBuilder.append(constraintViolation.getMessage()).append(",");
          ????????????}
          ????????????String?errorMessage?=?msgBuilder.toString();
          ????????????if(errorMessage.length()>1){
          ????????????????errorMessage?=?errorMessage.substring(0,errorMessage.length()-1);
          ????????????}
          ????????????errorWebResult.setInfo(errorMessage);
          ????????????return?errorWebResult;
          ????????}
          ????????errorWebResult.setInfo(ex.getMessage());
          ????????return?errorWebResult;
          ????}
          ?
          ????@ExceptionHandler(MethodArgumentNotValidException.class)
          ????@ResponseBody
          ????public?WebResult?resolveMethodArgumentNotValidException(MethodArgumentNotValidException?ex){
          ????????WebResult?errorWebResult?=?new?WebResult(WebResult.FAILED);
          ????????List??objectErrors?=?ex.getBindingResult().getAllErrors();
          ????????if(!CollectionUtils.isEmpty(objectErrors))?{
          ????????????StringBuilder?msgBuilder?=?new?StringBuilder();
          ????????????for?(ObjectError?objectError?:?objectErrors)?{
          ????????????????msgBuilder.append(objectError.getDefaultMessage()).append(",");
          ????????????}
          ????????????String?errorMessage?=?msgBuilder.toString();
          ????????????if?(errorMessage.length()?>?1)?{
          ????????????????errorMessage?=?errorMessage.substring(0,?errorMessage.length()?-?1);
          ????????????}
          ????????????errorWebResult.setInfo(errorMessage);
          ????????????return?errorWebResult;
          ????????}
          ????????errorWebResult.setInfo(ex.getMessage());
          ????????return?errorWebResult;
          ????}
          }
          ?

          7、相關標準

          JSR 303 是Bean驗證的規(guī)范 ,Hibernate Validator 是該規(guī)范的參考實現(xiàn),它除了實現(xiàn)規(guī)范要求的注解外,還額外實現(xiàn)了一些注解。
          validation-api-1.1.0.jar 包括如下約束注解:

          約束注解說明
          @AssertFalse被注釋的元素必須為 false
          @AssertTrue被注釋的元素必須為 true
          @DecimalMax(value)被注釋的元素必須是一個數(shù)字,其值必須小于等于指定的最大值
          @DecimalMin(value)被注釋的元素必須是一個數(shù)字,其值必須大于等于指定的最小值
          @Digits (integer, fraction)被注釋的元素必須是一個數(shù)字,其值必須在可接受的范圍內(nèi)
          @Null被注釋的元素必須為 null
          @NotNull被注釋的元素必須不為 null
          @Min(value)被注釋的元素必須是一個數(shù)字,其值必須大于等于指定的最小值
          @Max(value)被注釋的元素必須是一個數(shù)字,其值必須小于等于指定的最大值
          @Size(max, min)被注釋的元素的大小必須在指定的范圍內(nèi)
          @Past被注釋的元素必須是一個過去的日期
          @Future被注釋的元素必須是一個將來的日期
          @Pattern(value)被注釋的元素必須符合指定的正則表達式

          hibernate-validator-5.3.6.jar 包括如下約束注解:

          約束注解說明
          @Email被注釋的元素必須是電子郵箱地址
          @Length被注釋的字符串的大小必須在指定的范圍內(nèi)
          @NotBlank被注釋的字符串的必須非空
          @NotEmpty被注釋的字符串、集合、Map、數(shù)組必須非空
          @Range被注釋的元素必須在合適的范圍內(nèi)
          @SafeHtml被注釋的元素必須是安全Html
          @URL被注釋的元素必須是有效URL

          8、參數(shù)校驗原理

          這篇文章?寫得比較深入,我沒有太理解。

          9、本文源碼

          公司不讓上傳源碼到GitHub,可以參加這篇文章。

          10、同時校驗2個或更多個字段/參數(shù)

          常見的場景之一是,查詢某信息時要輸入開始時間和結束時間。顯然,結束時間要≥開始時間。可以在查詢VO類上使用自定義注解,下面的例子來自這里。劃重點:@ValidAddress使用在類上。

          @ValidAddress
          public?class?Address?{
          ?
          ????@NotNull
          ????@Size(max?=?50)
          ????private?String?street1;
          ?
          ????@Size(max?=?50)
          ????private?String?street2;
          ?
          ????@NotNull
          ????@Size(max?=?10)
          ????private?String?zipCode;
          ?
          ????@NotNull
          ????@Size(max?=?20)
          ????private?String?city;
          ?
          ????@Valid
          ????@NotNull
          ????private?Country?country;
          ?
          ????//?Getters?and?setters
          }


          public?class?Country?{
          ?
          ????@NotNull
          ????@Size(min?=?2,?max?=?2)
          ????private?String?iso2;
          ?
          ????//?Getters?and?setters
          }

          @Documented
          @Target(TYPE)
          @Retention(RUNTIME)
          @Constraint(validatedBy?=?{?MultiCountryAddressValidator.class?})
          public?@interface?ValidAddress?{
          ?
          ????String?message()?default?"{com.example.validation.ValidAddress.message}";
          ?
          ????Class[]?groups()?default?{};
          ?
          ????Class[]?payload()?default?{};
          }


          public?class?MultiCountryAddressValidator?
          ???????implements?ConstraintValidator?{
          ?
          ????public?void?initialize(ValidAddress?constraintAnnotation)?{
          ?
          ????}
          ?
          ????@Override
          ????public?boolean?isValid(Address?address,?
          ???????????????????????????ConstraintValidatorContext?constraintValidatorContext)?{
          ?
          ????????Country?country?=?address.getCountry();
          ????????if?(country?==?null?||?country.getIso2()?==?null?||?address.getZipCode()?==?null)?{
          ????????????return?true;
          ????????}
          ?
          ????????switch?(country.getIso2())?{
          ????????????case?"FR":
          ????????????????return?//?Check?if?address.getZipCode()?is?valid?for?France
          ????????????case?"GR":
          ????????????????return?//?Check?if?address.getZipCode()?is?valid?for?Greece
          ????????????default:
          ????????????????return?true;
          ????????}
          ????}
          }




          原文鏈接:

          https://blog.csdn.net/jinjiankang/article/details/89711493





          ??? ?



          感謝點贊支持下哈?

          瀏覽 62
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久草视频大香蕉 | 一区在线看 | 久操福利在线 | 青青草在线视频免费 | 欧美乱伦xx |