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

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

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

      都說了布爾類型的變量不要加 is 前綴,非要加,這不是坑我了嘛

      開心一刻

      今天心情不好,給哥們發語音
      我:哥們,晚上出來喝酒聊天吧
      哥們:咋啦,心情不好?
      我:嗯,剛剛在公交車上看見前女友了
      哥們:然后呢?
      我:給她讓座時,發現她懷孕了...
      哥們:所以難受了?
      我:不是她懷孕讓我難受,是她懷孕還坐公交車讓我難受
      哥們:不是,她跟著你就不用坐公交車了?不還是也要坐,有區別嗎?
      我默默的掛斷了語音,心情更難受了

      痛苦面具

      Java開發手冊

      作為一個 javaer,我們肯定看過 AlibabaJava開發手冊,作為國內Java開發領域的標桿性編碼規范,我們或多或少借鑒了其中的一些規范,其中有一點

      布爾值變量命名規約

      我印象特別深,也一直在奉行,自己還從未試過用 is 作為布爾類型變量的前綴,不知道會有什么坑;正好前段時間同事這么用了,很不幸,他挖坑,我踩坑,阿西吧!

      坑爹了

      is前綴的布爾變量有坑

      為了復現問題,我先簡單搞個 demo;調用很簡單,服務 workflow 通過 openfeign 調用 offline-sync,代碼結構如下

      項目模塊結構

      qsl-data-govern-common:整個項目的公共模塊

      qsl-offline-sync:離線同步

      • qsl-offline-sync-api:向外提供 openfeign 接口
      • qsl-offline-sync-common:離線同步公共模塊
      • qsl-offline-sync-server:離線同步服務

      qsl-workflow:工作流

      • qsl-workflow-api:向外提供 openfeign 接口,暫時空實現
      • qsl-workflow-common:工作流公共模塊
      • qsl-workflow-server:工作流服務

      完整代碼:qsl-data-govern

      qsl-offline-sync-server 提供刪除接口

      /**
       * @author 青石路
       */
      @RestController
      @RequestMapping("/task")
      public class SyncTaskController {
      
          private static final Logger LOG = LoggerFactory.getLogger(SyncTaskController.class);
      
          @PostMapping("/delete")
          public ResultEntity<String> delete(@RequestBody SyncTaskDTO syncTask) {
              // TODO 刪除處理
              LOG.info("刪除任務[taskId={}]", syncTask.getTaskId());
              return ResultEntity.success("刪除成功");
          }
      }
      

      qsl-offline-sync-api 對外提供 openfeign 接口

      /**
       * @author 青石路
       */
      @FeignClient(name = "data-govern-offline-sync", contextId = "dataGovernOfflineSync", url = "${offline.sync.server.url}")
      public interface OfflineSyncApi {
      
          @PostMapping(value = "/task/delete")
          ResultEntity<String> deleteTask(@RequestBody SyncTaskDTO syncTaskDTO);
      }
      

      qsl-workflow-server 調用 openfeign 接口

      /**
       * @author 青石路
       */
      @RestController
      @RequestMapping("/definition")
      public class WorkflowController {
      
          private static final Logger LOG = LoggerFactory.getLogger(WorkflowController.class);
      
          @Resource
          private OfflineSyncApi offlineSyncApi;
      
          @PostMapping("/delete")
          public ResultEntity<String> delete(@RequestBody WorkflowDTO workflow) {
              LOG.info("刪除工作流[workflowId={}]", workflow.getWorkflowId());
              // 1.查詢工作流節點,查到離線同步節點(taskId = 1)
              // 2.刪除工作流節點,刪除離線同步節點
              ResultEntity<String> syncDeleteResult = offlineSyncApi.deleteTask(new SyncTaskDTO(1L));
              if (syncDeleteResult.getCode() != 200) {
                  LOG.error("刪除離線同步任務[taskId={}]失敗:{}", 1, syncDeleteResult.getMessage());
                  ResultEntity.fail(syncDeleteResult.getMessage());
              }
              return ResultEntity.success("刪除成功");
          }
      }
      

      邏輯是不是很簡單?我們啟動兩個服務,然后發起 http 請求

      POST http://localhost:8081/data-govern/workflow/definition/delete
      Content-Type: application/json

      {
      "workflowId": 99
      }

      此時 qsl-offline-sync-server 日志輸出如下

      2025-06-30 14:53:06.165|INFO|http-nio-8080-exec-4|25|c.q.s.s.controller.SyncTaskController :刪除任務[taskId=1]

      至此,一切都很正常,第一版也是這么對接的;后面 offline-sync 進行調整,刪除接口增加了一個參數:isClearData

      public class SyncTaskDTO {
      
          public SyncTaskDTO(){}
      
          public SyncTaskDTO(Long taskId, Boolean isClearData) {
              this.taskId = taskId;
              this.isClearData = isClearData;
          }
      
          private Long taskId;
          private Boolean isClearData = false;
      
          public Long getTaskId() {
              return taskId;
          }
      
          public void setTaskId(Long taskId) {
              this.taskId = taskId;
          }
      
          public Boolean getClearData() {
              return isClearData;
          }
      
          public void setClearData(Boolean clearData) {
              isClearData = clearData;
          }
      }
      

      然后實現對應的邏輯

      /**
       * @author 青石路
       */
      @RestController
      @RequestMapping("/task")
      public class SyncTaskController {
      
          private static final Logger LOG = LoggerFactory.getLogger(SyncTaskController.class);
      
          @PostMapping("/delete")
          public ResultEntity<String> delete(@RequestBody SyncTaskDTO syncTask) {
              // TODO 刪除處理
              LOG.info("刪除任務[taskId={}]", syncTask.getTaskId());
              if (syncTask.getClearData()) {
                  LOG.info("清空任務[taskId={}]歷史數據", syncTask.getTaskId());
                  // TODO 清空歷史數據
              }
              return ResultEntity.success("刪除成功");
          }
      }
      

      調整完之后,同事通知我,讓我做對 qsl-workflow 做對應的調整。調整很簡單,qsl-workflow 刪除時直接傳 true 即可

      /**
       * @author 青石路
       */
      @RestController
      @RequestMapping("/definition")
      public class WorkflowController {
      
          private static final Logger LOG = LoggerFactory.getLogger(WorkflowController.class);
      
          @Resource
          private OfflineSyncApi offlineSyncApi;
      
          @PostMapping("/delete")
          public ResultEntity<String> delete(@RequestBody WorkflowDTO workflow) {
              LOG.info("刪除工作流[workflowId={}]", workflow.getWorkflowId());
              // 1.查詢工作流節點,查到離線同步節點(taskId = 1)
              // 2.刪除工作流節點,刪除離線同步節點
              // 刪除離線同步任務,isClearData直接傳true
              ResultEntity<String> syncDeleteResult = offlineSyncApi.deleteTask(new SyncTaskDTO(1L, true));
              if (syncDeleteResult.getCode() != 200) {
                  LOG.error("刪除離線同步任務[taskId={}]失敗:{}", 1, syncDeleteResult.getMessage());
                  ResultEntity.fail(syncDeleteResult.getMessage());
              }
              return ResultEntity.success("刪除成功");
          }
      }
      

      調整完成之后,發起 http 請求,發現歷史數據沒有被清除,看日志發現

      LOG.info("清空任務[taskId={}]歷史數據", syncTask.getTaskId());

      沒有打印,參數明明傳的是 true 吖!!!

      offlineSyncApi.deleteTask(new SyncTaskDTO(1L, true));

      這是哪里出了問題?

      20240115000802

      問題排查

      因為 qsl-offline-sync-api 是直接引入的,并非我實現的,所以我第一時間找到了其實現者,反饋了問題后讓其自測下;一開始他還很自信,說這么簡單怎么會有問題

      640 (15)

      當他啟動 qsl-offline-sync-server 后,發起 http 請求

      POST http://localhost:8080/data-govern/sync/task/delete
      Content-Type: application/json

      {
      "taskId": 123,
      "isClearData": true
      }

      發現 isClearData 的值是 false

      isClearData是false

      此刻,疑問從我的額頭轉移到了他的額頭上,他懵逼了,我輕松了。為了功能能夠正常交付,我還是決定看下這個問題,沒有了心理壓力,也許更容易發現問題所在。第一眼看到 isClearData,我就隱約覺得有問題,所以我決定仔細看下 SyncTaskDTO 這個類,發現 isClearDatasettergetter 方法有點不一樣

      private Boolean isClearData = false;
      
      public Boolean getClearData() {
          return isClearData;
      }
      
      public void setClearData(Boolean clearData) {
          isClearData = clearData;
      }
      

      方法名是不是少了 Is?帶著這個疑問我找到了同事,問他 settergetter 為什么要這么命名?他說是 idea 工具自動生成的(也就是我們平時用到的idea自動生成setter、getter方法的功能)

      idea_setter-getter

      我讓他把 Is 補上試試

      private Boolean isClearData = false;
      
      public Boolean getIsClearData() {
          return isClearData;
      }
      
      public void setIsClearData(Boolean isClearData) {
          this.isClearData = isClearData;
      }
      

      發現傳值正常了,他回過頭看著我,我看著他,兩人同時提問

      他:為什么加了 Is 就可以了?

      我:布爾類型的變量,你為什么要加 is 前綴?

      問題延申

      作為一個嚴謹的開發,不只是要知其然,更要知其所以然;關于

      為什么加了 Is 就可以了

      這個問題,我們肯定是要會上一會的;會這個問題之前,我們先來捋一下參數的流轉,因為是基于 Spring MVC 實現的 Web 應用,所以我們可以這么問 deepseek

      Spring MVC 是如何將前端參數轉換成POJO的

      能夠查到如下重點信息

      springmvc參數轉換

      RequestResponseBodyMethodProcessorresolveArgument

      /**
       * Throws MethodArgumentNotValidException if validation fails.
       * @throws HttpMessageNotReadableException if {@link RequestBody#required()}
       * is {@code true} and there is no body content or if there is no suitable
       * converter to read the content with.
       */
      @Override
      public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
              NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
      
          parameter = parameter.nestedIfOptional();
          Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());
          String name = Conventions.getVariableNameForParameter(parameter);
      
          if (binderFactory != null) {
              WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name);
              if (arg != null) {
                  validateIfApplicable(binder, parameter);
                  if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
                      throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());
                  }
              }
              if (mavContainer != null) {
                  mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());
              }
          }
      
          return adaptArgumentIfNecessary(arg, parameter);
      }
      

      正是解析參數的地方,我們打個斷點,再發起一次 http 請求

      斷點調試

      很明顯,readWithMessageConverters 是處理并轉換參數的地方,繼續跟進去會來到 MappingJackson2HttpMessageConverterreadJavaType 方法

      jackson綁定參數

      此刻我們可以得到,是通過 jackson 完成數據綁定與數據轉換的。繼續跟進,會看到 isClearData 的賦值過程

      set反射設值

      通過前端傳過來的參數 isClearData 找對應的 setter方法是 setIsClearData,而非 setClearData,所以問題

      為什么加了 Is 就可以了

      是不是就清楚了?

      問題解決

      1. 按上述方式調整 isClearDatasettergetter 方法

        帶上 is

        public Boolean getIsClearData() {
            return isClearData;
        }
        
        public void setIsClearData(Boolean isClearData) {
            this.isClearData = isClearData;
        }
        
      2. 布爾類型的變量,不用 is 前綴

        可以用 if 前綴

        private Boolean ifClearData = false;
        
        public Boolean getIfClearData() {
            return ifClearData;
        }
        
        public void setIfClearData(Boolean ifClearData) {
            this.ifClearData = ifClearData;
        }
        
      3. 可以結合 @JsonProperty 來處理

        @JsonProperty("isClearData")
        private Boolean isClearData = false;
        

      總結

      1. Spring MVC 對參數的綁定與轉換,內容不同,采用的處理器也不同

        1. form表單數據(application/x-www-form-urlencoded)

          處理器:ServletModelAttributeMethodProcessor

        2. JSON 數據 (application/json)

          處理器:RequestResponseBodyMethodProcessor
          轉換器:MappingJackson2HttpMessageConverter

        3. 多部分文件 (multipart/form-data)

          處理器:MultipartResolver

      2. POJO 的布爾類型變量,不要加 is 前綴

        命名不符合規范,集成第三方框架的時候就很容易出不好排查的問題

        成不了規范的制定者,那就老老實實遵循規范!

      posted @ 2025-07-01 09:14  青石路  閱讀(1482)  評論(26)    收藏  舉報
      主站蜘蛛池模板: 亚洲日本欧洲二区精品| 国产一区二区三区色成人| 少妇高清一区二区免费看| 贺兰县| 成人亚洲一级午夜激情网| 老色批国产在线观看精品| 啦啦啦中文在线观看日本| 噜妇插内射精品| 国产精品自在线拍国产手机版| 又大又粗又爽18禁免费看| 97av| 亚洲AV无码AV在线影院| 精选国产av精选一区二区三区| 天啦噜国产精品亚洲精品| 亚洲国产另类久久久精品| 日韩一级伦理片一区二区| 大桥未久亚洲无av码在线| 国产精品午夜福利免费看| 精品国产一区av天美传媒| 万载县| 成全高清在线播放电视剧| 国产a网站| 成人午夜在线观看日韩| 一个色综合色综合色综合| 精品无人乱码一区二区三区的优势| 精品偷拍一区二区三区| 亚洲区一区二区激情文学| 成年女人免费毛片视频永久| 97色成人综合网站| 亚洲综合一区国产精品| 亚洲自偷自拍熟女另类| 韩国三级+mp4| 无码视频伊人| 国产一区日韩二区欧美三区| 人人妻人人澡人人爽曰本| 亚洲国产在一区二区三区| 日韩一区二区三区女优丝袜| 日韩精品一二三黄色一级| 国产精品自拍中文字幕| 四虎精品国产精品亚洲精| 重口SM一区二区三区视频|