1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

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

        共 5148字,需瀏覽 11分鐘

         ·

        2020-10-07 17:00

        點擊上方藍色字體,選擇“標(biāo)星公眾號”

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

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

        1、前言

        在控制器類的方法里自己寫校驗邏輯代碼當(dāng)然也可以,只是代碼比較丑陋,有點“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;
        }

        用法是:路徑變量:正則表達式。當(dāng)請求URI不滿足正則表達式時,客戶端將收到404錯誤碼。不方便的地方是,不能通過捕獲異常的方式,向前端返回統(tǒng)一的、自定義格式的響應(yī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,更多注解參見相關(guān)標(biāo)準(zhǔn)小節(jié)。

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

        當(dāng)參數(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注解要求必須是相對當(dāng)前時間來講“未來的”某個時間。

        @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必須是預(yù)定義的那幾個值,不能隨便寫";
        ?
        ????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、異常攔截器

        通過設(shè)置全局異常處理器,統(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、相關(guān)標(biāo)準(zhǔn)

        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ù)

        常見的場景之一是,查詢某信息時要輸入開始時間和結(jié)束時間。顯然,結(jié)束時間要≥開始時間??梢栽诓樵僔O類上使用自定義注解,下面的例子來自這里。劃重點:@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
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

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

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            操逼啊 | 超碰操逼网 | 欧美美女被插 | 黄色A级 欧美成人777奇米影视91色 | 日韩污网站 | 欧美一级片在线播放视频 | 玖玖99 | 久久福利导航 | 少妇饥渴偷公乱第1章 | 人人爱精品 |