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

          一波帶走,SpringBoot 中的各種參數校驗方案匯總

          共 4424字,需瀏覽 9分鐘

           ·

          2022-06-08 23:04

          ????關注后回復?“進群”?,拉你進程序員交流群????

          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錯誤碼。不方便的地方是,不能通過捕獲異常的方式,向前端返回統一的、自定義格式的響應參數。

          3、方法參數校驗

          @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";
          }

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

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

          當參數是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;
          ????。。。
          }

          其中,Future注解要求必須是相對當前時間來講“未來的”某個時間。

          @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無效時的提示內容
          ????String?message()?default?"flag必須是預定義的那幾個值,不能隨便寫";

          ????Class[]?groups()?default?{};

          ????Class[]?payload()?default?{};
          }
          import?javax.validation.ConstraintValidator;
          import?javax.validation.ConstraintValidatorContext;

          public?class?FlagValidatorClass?implements?ConstraintValidator<FlagValidator,Object>?{
          ????/**
          ?????*?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、異常攔截器

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

          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ī)范的參考實現,它除了實現規(guī)范要求的注解外,還額外實現了一些注解。

          validation-api-1.1.0.jar 包括如下約束注解:

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

          8、參數校驗原理

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

          https://blog.csdn.net/wt_better/article/details/84635010

          9、同時校驗2個或更多個字段/參數

          常見的場景之一是,查詢某信息時要輸入開始時間和結束時間。顯然,結束時間要≥開始時間??梢栽诓樵僔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<ValidAddress,?Address>?
          {

          ????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;
          ????????}
          ????}
          }

          來源:blog.csdn.net/jinjiankang/article/details/89711493

          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?面試題?資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網盤了,歡迎下載!

          點擊??卡片,關注后回復【面試題】即可獲取

          在看點這里好文分享給更多人↓↓

          瀏覽 33
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  99欧美精品在线观看 | 国产99久久久精品无码 | 超碰女| 国内最新成人AV | 精品人妻天天爽夜夜爽视频 |