91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot項目全局異常處理會遇到哪些問題

發布時間:2022-01-21 11:56:14 來源:億速云 閱讀:223 作者:小新 欄目:開發技術

這篇文章主要介紹了springboot項目全局異常處理會遇到哪些問題,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

問題一:全局異常抽離出來后,業務錯誤碼如何定義?

之前團隊的業務錯誤碼定義是:業務服務前綴 + 業務模塊 + 錯誤碼,如果是識別不了的異常,則使用業務前綴 + 固定模塊碼 + 固定錯誤碼。

之前的全局異常偽代碼如下

@RestControllerAdvice
@Slf4j
public class GlobalExceptionBaseHandler {

   
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public AjaxResult handleException(Exception e) {
        String servicePrifix = "U";
        String moudleCode = "001";
        String code = "0001";
        String errorCode = servicePrifix + moudleCode + code;
        String msg = e.getMessage();
        if(StringUtils.isEmpty(msg)){
            msg = "服務端異常";
        }
        log.error(msg, e);
        return AjaxResult.error(msg, errorCode);
    }
    }
現在全局異常抽離出來后,那個業務服務前綴如何識別?之前未抽離時,業務服務前綴各個業務服務直接寫死在代碼里。

當時我們臨時的解決方案是通過spring.application.name來解決。因為全局異常代碼塊抽離出來后,最終還是要被服務引入的。因此獲取業務服務前綴的偽代碼可以通過如下獲取

public enum  ServicePrefixEnum {

    USER_SERVICE("U","用戶中心");

    private final String servicePrefix;

    private final String serviceDesc;

    ServicePrefixEnum(String servicePrefix,String serviceDesc) {
        this.servicePrefix = servicePrefix;
        this.serviceDesc = serviceDesc;
    }

    public String getServicePrefix() {
        return servicePrefix;
    }

    public String getServiceDesc() {
        return serviceDesc;
    }
}
public String getServicePrefix(@Value("${spring.application.name}") String serviceName){
      return ServicePrefixEnum.valueOf(serviceName).getServicePrefix();
    }

但這種方案其實是存在弊端

弊端一: 通過枚舉硬編碼,預設了目前了微服務名稱,一旦項目改變了微服務名,就找不到服務前綴了。

弊端二: 如果新上線了業務服務模塊,這個枚舉類還得改動

后面我們在全局異常jar中增加了自定義業務碼的配置,業務人員僅需在springboot配置文件配置,形如下

lybgeek:
  bizcode:
    prefix: U

此時全局異常改造示例形如下

@RestControllerAdvice
@Slf4j
public class GlobalExceptionBaseHandler {
    
    
    @Autowired
    private ServiceCodeProperties serviceCodeProperties;

   
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public AjaxResult handleException(Exception e) {
        String servicePrifix = serviceCodeProperties.getPrifix();
        String moudleCode = "001";
        String code = "0001";
        String errorCode = servicePrifix + moudleCode + code;
        String msg = e.getMessage();
        if(StringUtils.isEmpty(msg)){
            msg = "服務端異常";
        }
        log.error(msg, e);
        return AjaxResult.error(msg, errorCode);
    }
}

問題二:全局異常因引入了和業務相同的依賴jar,但jar存在版本差異

如果全局異常直接如下寫,是不存在問題。示例如下

@RestControllerAdvice
@Slf4j
public class GlobalExceptionBaseHandler {


    @Autowired
    private ServiceCodeProperties serviceCodeProperties;

    
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public AjaxResult handleException(Exception e) {
        String servicePrifix = serviceCodeProperties.getPrifix();
        String moudleCode = "001";
        String code = "0001";
        String errorCode = servicePrifix + moudleCode + code;
        String msg = e.getMessage();
        if(StringUtils.isEmpty(msg)){
            msg = "服務端異常";
        }
        log.error(msg, e);
        return AjaxResult.error(msg, HttpStatus.INTERNAL_SERVER_ERROR.value());
    }


    @ExceptionHandler(BizException.class)
    public AjaxResult handleException(BizException e)
    {
        return AjaxResult.error(e.getMessage(), e.getErrorCode());
    }

}

即全局異常直接分為業務異常和Execption這兩種,這樣劃分的弊端在于沒辦法細分異常,而且也使項目組定義的模塊碼和業務碼沒法細分。因此我們也列出常用可以預知的系統異常,示例如下

/**
     *參數驗證失敗
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public AjaxResult handleException(ConstraintViolationException e)
    {
        log.error("參數驗證失敗", e);
        return AjaxResult.error("參數驗證失敗", HttpStatus.BAD_REQUEST.value());
    }

   /**
     * 數據庫異常
     * @param e
     * @return
     */
    @ExceptionHandler({SQLException.class, MybatisPlusException.class,
            MyBatisSystemException.class, org.apache.ibatis.exceptions.PersistenceException.class,
            BadSqlGrammarException.class
    })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public AjaxResult dbException(Exception e) {
        String msg = ExceptionUtil.getExceptionMessage(e);
        log.error(msg, e);
        return AjaxResult.error(msg,HttpStatus.BAD_REQUEST.value());
    }

    /**
     * 數據庫中已存在該記錄
     * @param e
     * @return
     */
    @ExceptionHandler(DuplicateKeyException.class)
    @ResponseStatus(HttpStatus.CONFLICT)
    public AjaxResult handleException(DuplicateKeyException e)
    {
        log.error("數據庫中已存在該記錄", e);
        return AjaxResult.error("數據庫中已存在該記錄", HttpStatus.CONFLICT.value());
    }

不過這樣導致了一個問題,就是全局異常和業務方使用相同的依賴jar,但存在版本差異時,可能就會存在依賴沖突,導致業務項目啟動報錯。因此解決方案就是在pom文件加入optional標簽。示例如下

<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <optional>true</optional>
        </dependency>

這標簽的意思這jar坐標是可選的,因此如果項目中已經有引入該jar的坐標,就直接用該jar的坐標

問題三:引入maven optional標簽后,因業務沒引入全局異常需要的jar,導致項目啟動報錯

這個問題的產生:舉個示例,我們的業務微服務項目有聚合層,某些聚合層是不需要依賴存儲介質,比如mysql。因此這些聚合層項目pom就不會引入類似mybatis相關的依賴。但我們的全局異常又需要類似mybatis相關的依賴,這樣導致如果要引用全局異常模塊,有得額外加入業務方不需要的jar。

因此springboot的條件注解就派上用場了,利用@ConditionalOnClass注解。示例如下

@RestControllerAdvice
@Slf4j
@ConditionalOnClass({SQLException.class, MybatisPlusException.class,
        MyBatisSystemException.class, org.apache.ibatis.exceptions.PersistenceException.class,
        BadSqlGrammarException.class, DuplicateKeyException.class})
public class GlobalExceptionDbHandler {

    /**
     * 數據庫異常
     * @param e
     * @return
     */
    @ExceptionHandler({SQLException.class, MybatisPlusException.class,
            MyBatisSystemException.class, org.apache.ibatis.exceptions.PersistenceException.class,
            BadSqlGrammarException.class
    })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public AjaxResult dbException(Exception e) {
        String msg = ExceptionUtil.getExceptionMessage(e);
        log.error(msg, e);
        return AjaxResult.error(msg,HttpStatus.BAD_REQUEST.value());
    }

    /**
     * 數據庫中已存在該記錄
     * @param e
     * @return
     */
    @ExceptionHandler(DuplicateKeyException.class)
    @ResponseStatus(HttpStatus.CONFLICT)
    public AjaxResult handleException(DuplicateKeyException e)
    {
        log.error("數據庫中已存在該記錄", e);
        return AjaxResult.error("數據庫中已存在該記錄", HttpStatus.CONFLICT.value());
    }
}

@ConditionalOnClass這個注解的作用就是如果classpath存在指定的類,則該注解上的類會生效。

同時這邊有個細節點,就是全局異常可能就得細分,即把原來的大一統的全局異常,按業務場景分開,比如存儲介質相關的存儲異常,web相關異常

感謝你能夠認真閱讀完這篇文章,希望小編分享的“springboot項目全局異常處理會遇到哪些問題”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

万盛区| 巴林右旗| 隆昌县| 托克逊县| 永泰县| 兴仁县| 武安市| 诏安县| 平顶山市| 浏阳市| 揭东县| 木兰县| 黄山市| 岢岚县| 彭水| 荔浦县| 林西县| 泸定县| 黄梅县| 简阳市| 贺兰县| 河北省| 唐山市| 游戏| 锡林郭勒盟| 福州市| 湘潭市| 安福县| 抚松县| 阿克| 台东市| 玉门市| 黄山市| 临洮县| 莲花县| 尚义县| 应城市| 布尔津县| 广南县| 泽州县| 湘潭市|