<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      shuijibaobao

      導航

       
      1. JSR 303是什么?

      JSR 303(Java Specification Request 303),也稱為Bean Validation,是Java中的一個規范,用于定義Java對象的校驗規則。
      1.1 JSR 303的主要功能

          注解驅動:通過注解直接在Java類上定義校驗規則。
          內置約束:如@NotNull、@Size、@Min、@Max等。
          自定義約束:可以定義自定義的校驗注解和邏輯。
          分組校驗:支持對不同場景(如創建和更新)進行分組校驗。

      1.2 常用注解

          @NotNull:驗證注解的元素值不是null。
          @Size:驗證注解的元素的大小在指定范圍內。
          @Min和@Max:驗證注解的元素值在指定范圍內。
          @Email:驗證注解的元素是一個合法的電子郵件地址。

      2. 使用步驟

      JSR 303 是一個規范,所以需要具體的實現。Hibernat Bean Validator 就是Bean Validator的實現

      2.1.引入庫

              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-validation</artifactId>
              </dependency>
      
              <dependency>
                  <groupId>javax.validation</groupId>
                  <artifactId>validation-api</artifactId>
                  <version>2.0.1.Final</version>
              </dependency>
      
              <dependency>
                  <groupId>org.hibernate</groupId>
                  <artifactId>hibernate-validator</artifactId>
                  <version>8.0.1.Final</version>
              </dependency>

      2.2 實體類編寫校驗規則

      代碼如下(示例):

      @Data
      public class BrandEntity implements Serializable {
        
          /**
           * 品牌ID,用于標識品牌。
           * 
           * 此字段通過注解進行了不同的驗證邏輯配置,以適應不同的業務場景。
           * 在更新操作(UpdateGroup)中,要求此字段不為空,確保了更新操作有明確的目標品牌ID。
           * 在新增操作(AddGroup)中,要求此字段為空,因為新增品牌時不應該預先指定ID。
           * 這種通過注解進行驗證的方式,提高了代碼的靈活性和可維護性,避免了在業務邏輯中硬編碼驗證邏輯。
           */
          @NotNull(message = "修改必須指定品牌id",groups = {UpdateGroup.class})
          @Null(message = "新增不能指定id",groups = {AddGroup.class})
          private Long brandId;
      
      
          /**
           * 品牌名稱字段。
           * 
           * 該字段是必填的,不允許為空字符串,這在添加和更新品牌信息時都必須遵守。
           * 使用@NotBlank注解來強制驗證品牌名的非空性,如果為空,則會觸發驗證失敗,
           * 返回相應的錯誤消息。
           */
          @NotBlank(message = "品牌名必須提交",groups = {AddGroup.class,UpdateGroup.class})
          private String name;
      
      
        
          /**
           * 品牌logo地址
           * 
           * 此字段在添加(AddGroup)和更新(UpdateGroup)時都必須是一個合法的URL地址,
           * 以確保公司徽標的鏈接是有效和可訪問的。使用@URL注解進行驗證,
           * 如果不符合URL格式,則會提示指定的錯誤信息。
           * 
           * 使用@NotBlank注解確保在添加時該字段不為空,為空則認為是無效的輸入。
           * 這是因為在更新時,如果用戶沒有提供新的徽標URL,可以保留舊的URL,
           * 所以在更新組(UpdateGroup)中,@NotBlank約束被移除,允許為空。
           */
          @NotBlank(groups = {AddGroup.class})
          @URL(message = "logo必須是一個合法的url地址",groups={AddGroup.class,UpdateGroup.class})
          private String logo;
      
          
          /**
           * 展示狀態字段,用于標記對象的展示狀態。
           * 顯示狀態[0-不顯示;1-顯示]
           * 
           * 此字段受到兩個驗證組(AddGroup, UpdateStatusGroup)的約束。
           * 在這兩個組中,該字段不能為空(@NotNull)且其值必須在預定義的列表中(@ListValue)。
           * 這樣的設計確保了在添加對象和更新狀態操作時,展示狀態的值是有效且受控的。
           * 
           * @NotNull(groups = {AddGroup.class, UpdateStatusGroup.class})
           * 表明在AddGroup和UpdateStatusGroup驗證組中,此字段不能為空。
           * @ListValue(vals={0,1},groups = {AddGroup.class, UpdateStatusGroup.class})
           * 表明在AddGroup和UpdateStatusGroup驗證組中,此字段的值必須是0或1。
           */
          @NotNull(groups = {AddGroup.class, UpdateStatusGroup.class})
          @ListValue(vals={0,1},groups = {AddGroup.class, UpdateStatusGroup.class})
          private Integer showStatus;
      
          /**
           * 字段firstLetter用于存儲實體的首字母。
           * 該字段的驗證有以下規則:
           * 1. 在添加(AddGroup)時,不能為空,確保數據完整性。
           * 2. 在添加(AddGroup)和更新(UpdateGroup)時,必須是一個字母,確保數據的格式符合預期。
           * 這些驗證規則通過注解的方式進行聲明,以在運行時對數據進行校驗。
           */
          @NotEmpty(groups={AddGroup.class})
          @Pattern(regexp="^[a-zA-Z]$",message = "檢索首字母必須是一個字母",groups={AddGroup.class,UpdateGroup.class})
          private String firstLetter;
      
       
          /**
           * 排序字段,用于控制元素的顯示順序。
           * 
           * @NotNull 標注指示該字段在添加(AddGroup)時不能為空,確保了排序值的有效性。
           * @Min 標注指定了排序值必須大于等于0,適用于添加(AddGroup)和更新(UpdateGroup)操作,保證了排序的邏輯正確性。
           */
          @NotNull(groups={AddGroup.class})
          @Min(value = 0,message = "排序必須大于等于0",groups={AddGroup.class,UpdateGroup.class})
          private Integer sort;
          
      }

      2.3 自定義約束

      通過上面的代碼可以看出,如果要指定注解作用的范圍,就要自己添加分組。

      AddGroup

      public interface AddGroup {
      }

      UpdateGroup

      public interface UpdateGroup {
      }

      UpdateStatusGroup

      public interface UpdateStatusGroup {
      }

      上述代碼中為了對狀態取值進行驗證,我們采用了自定義驗證器的方式

      ListValue

      @Documented
      @Constraint(validatedBy = { ListValueConstraintValidator.class })
      @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
      @Retention(RUNTIME)
      public @interface ListValue {
      
          String message() default "{com.xunqi.common.valid.ListValue.message}";
      
          Class<?>[] groups() default { };
      
          Class<? extends Payload>[] payload() default { };
      
          int[] vals() default { };
      }

      3. 業務層使用

      /**
       * <p>
       * 商品品牌 前端控制器
       * </p>
       *
       * @author shiqi
       * @version 1.0.0
       * @createTime 2024-06-26
       */
      @RestController
      @RequestMapping("product/brand")
      public class BrandController {
          /**
           * 保存品牌信息。
           * <p>
           * 該方法通過@RequestMapping注解映射了"/save"的HTTP請求,用于保存BrandEntity對象。
           * 使用@Validated注解對brandEntity參數進行驗證,確保添加或修改品牌時數據的合法性。
           * BindingResult參數用于接收驗證后的錯誤信息,可以進一步處理和反饋給前端。
           * <p>
           * 方法返回一個R對象,通常表示操作的成功或失敗狀態。
           *
           * @param brandEntity 品牌實體對象,包含待保存的品牌信息。
           * @param bindingResult 驗證結果對象,用于存儲brandEntity驗證過程中產生的錯誤信息。
           * @return 返回一個表示操作結果的對象,通常是一個包含成功狀態和相關消息的R對象。
           */
          @RequestMapping("/save")
          public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brandEntity, BindingResult bindingResult) {
              // 方法體中應包含保存品牌信息的具體邏輯,此處省略。
              return R.ok();
          }
      
      
      }

      4. 封裝統一異常

      4.1 業務異常狀態枚舉類

      /**
       * <p>
       * 描述:業務異常枚舉類
       * </p>
       *
       * @author shiqi
       * @version 1.0.0
       * @createTime 2024-06-26
       */
      public enum BizCodeEnum {
          UNKNOWN_EXCEPTION(10000,"系統未知異常"),
          VALID_EXCEPTION(10001,"參數格式校驗失敗"),
          TO_MANY_REQUEST(10002,"請求流量過大,請稍后再試"),
          SMS_CODE_EXCEPTION(10002,"驗證碼獲取頻率太高,請稍后再試"),
          PRODUCT_UP_EXCEPTION(11000,"商品上架異常"),
          USER_EXIST_EXCEPTION(15001,"存在相同的用戶"),
          PHONE_EXIST_EXCEPTION(15002,"存在相同的手機號"),
          NO_STOCK_EXCEPTION(21000,"商品庫存不足"),
          LOGIN_ACCOUNT_PASSWORD_EXCEPTION(15003,"賬號或密碼錯誤");
      
      
          private int code;
      
          private String message;
      
      
          BizCodeEnum(int code, String message) {
      
              this.code = code;
      
              this.message = message;
          }
      
      
          public int getCode() {
              return code;
          }
      
          public String getMessage() {
              return message;
          }
      }

      4.2 封裝統一返回結果

      /**
       * <p>
       *  統一返回結果
       * </p>
       *
       * @author shiqi
       * @version 1.0.0
       * @createTime 2024-06-26
       */
       public class R extends HashMap<String, Object> {
          private static final long serialVersionUID = 1L;
      
          public R setData(Object data) {
              put("data",data);
              return this;
          }
      
          //利用fastjson進行反序列化
          public <T> T getData(TypeReference<T> typeReference) {
              Object data = get("data");    //默認是map
              String jsonString = JSON.toJSONString(data);
              T t = JSON.parseObject(jsonString, typeReference);
              return t;
          }
      
          //利用fastjson進行反序列化
          public <T> T getData(String key,TypeReference<T> typeReference) {
              Object data = get(key);    //默認是map
              String jsonString = JSON.toJSONString(data);
              T t = JSON.parseObject(jsonString, typeReference);
              return t;
          }
      
          public R() {
              put("code", 0);
              put("msg", "success");
          }
      
          public static R error() {
              return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知異常,請聯系管理員");
          }
      
          public static R error(String msg) {
              return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
          }
      
          public static R error(int code, String msg) {
              R r = new R();
              r.put("code", code);
              r.put("msg", msg);
              return r;
          }
      
          public static R ok(String msg) {
              R r = new R();
              r.put("msg", msg);
              return r;
          }
      
          public static R ok(Map<String, Object> map) {
              R r = new R();
              r.putAll(map);
              return r;
          }
      
          public static R ok() {
              return new R();
          }
      
          public R put(String key, Object value) {
              super.put(key, value);
              return this;
          }
      
          public Integer getCode() {
      
              return (Integer) this.get("code");
          }
      
      }

      自定義校驗異常處理器

      /**
       * <p>
       *  集中處理所有異常
       * </p>
       *
       * @author shiqi
       * @version 1.0.0
       * @createTime 2024-06-26
       */
      
      @Slf4j
      @RestControllerAdvice(basePackages = {"com.shiqi.jsr303demo"})
      public class CustomExceptionControllerAdvice {
      
          /**
           * 處理方法參數不合法異常。
           * 當方法參數不滿足驗證條件時,Spring MVC會拋出MethodArgumentNotValidException異常。
           * 該異常處理器專門捕獲此類異常,以統一的方式處理參數驗證失敗的情況。
           *
           * @param e MethodArgumentNotValidException異常實例,包含驗證失敗的詳細信息。
           * @return 返回一個包含錯誤信息的響應對象。
           */
          @ExceptionHandler(value = MethodArgumentNotValidException.class)
          public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e){
              // 獲取驗證結果對象,其中包含了具體的驗證錯誤信息。
              BindingResult bindingResult = e.getBindingResult();
      
              // 初始化一個映射,用于存儲字段名和對應的錯誤信息。
              HashMap<String,String> errMap=new HashMap<String,String>();
      
              // 檢查是否有驗證錯誤,如果有,則遍歷所有字段錯誤,并將字段名和錯誤信息添加到errMap中。
              if (bindingResult.hasErrors()){
                  bindingResult.getFieldErrors().forEach((item)->{
                      errMap.put(item.getField(),item.getDefaultMessage());
                  });
              }
      
              // 返回一個包含錯誤代碼、錯誤消息和具體錯誤詳情的響應對象。
              // 錯誤代碼為400,表示客戶端請求錯誤,錯誤消息為"參數校驗不合法"。
              // errMap作為數據部分的一部分,包含了所有驗證失敗的字段和對應的錯誤信息。
              return R.error(400,"參數校驗不合法").put("data",errMap);
          }
      
          /**
           * 處理所有異常的控制器異常處理器。
           * <p>
           * 該方法旨在捕獲控制器層拋出的任何異常,無論是預期的業務異常還是未預期的運行時異常。
           * 它的目的是統一異常的處理方式,向客戶端返回一個標準的響應體,而不是直接暴露服務器內部錯誤信息。
           *
           * @param throwable 拋出的異常對象,無論異常類型為何。
           * @return 返回一個表示錯誤響應的R對象。這個響應體可以幫助客戶端識別請求處理過程中發生了什么錯誤。
           */
          @ExceptionHandler(value = Throwable.class)
          private R handleValidException(Throwable throwable) {
              // 記錄異常信息到日志系統,以便后續的問題排查和分析。
              log.error("出現異常{},異常類型{}", throwable.getMessage(), throwable.getClass());
              // 返回一個通用的錯誤響應體,通知客戶端請求處理過程中發生了錯誤。
              return R.error();
          }
      
      
      }

      5. 實際業務中的應用

          表單校驗:確保用戶輸入的數據合法,如用戶注冊、登錄、表單提交等。
          數據傳輸對象(DTO)校驗:在進行數據傳輸時,確保傳輸的數據符合預期,如API請求和響應。
          領域對象校驗:確保業務邏輯中的對象狀態合法,如訂單處理、支付處理等。

      使用JSR 303可以有效減少手動校驗代碼,簡化代碼結構,提高代碼可讀性和維護性。在實際應用中,常結合Spring框架和Hibernate Validator一起使用。

                              
      原文鏈接:https://blog.csdn.net/Hi_alan/article/details/139997617



      posted on 2024-08-19 21:46  水吉z  閱讀(196)  評論(0)    收藏  舉報
       
      主站蜘蛛池模板: 激情在线一区二区三区视频 | 广安市| 亚洲精品香蕉一区二区| 国产一级片内射在线视频| 亚洲精品人成网线在播放VA| 日本高清视频在线www色| 国产成人亚洲精品成人区| 99久久无码私人网站| 欧美成a人片在线观看久| 少妇熟女天堂网av| 日韩激情一区二区三区| 隆子县| 日韩欧美aⅴ综合网站发布| 国内精品视频一区二区三区 | 91精品国产自产91精品| 亚洲AV国产福利精品在现观看| 国产高清在线a视频大全| 无套内谢少妇高清毛片| 亚洲岛国成人免费av| 长泰县| 2020国产欧洲精品网站| 成人免费无遮挡在线播放 | 亚洲不卡一区三区三区四| 精品国产美女福到在线不卡| 欧美白妞大战非洲大炮| 中文字幕第一页国产| 国产精品亚洲二区在线播放| 亚洲欧洲日韩国内高清| 九九色这里只有精品国产| 久久这里只有精品免费首页| 久久亚洲精品中文字幕馆| 亚洲国产激情一区二区三区 | 国产亚洲精品97在线视频一| 最新成免费人久久精品| 色欧美片视频在线观看| 国产一区二区波多野结衣| 少妇被粗大的猛烈xx动态图| 国产日韩精品欧美一区灰| 宅男噜噜噜66网站高清| 龙海市| 久久精品蜜芽亚洲国产AV|