天天看點

微服務項目錯誤碼規範和多語言的錯誤消息

作者:簡簡單單程式員

在微服務項目中出現錯誤後最快定位錯誤的辦法就是有一個明确的錯誤碼提示,而微服務項目中往往由不同的人開發不同的子產品,這是如果沒有統一的錯誤碼規範會導緻多個子產品出現一個錯誤碼而含義不同導緻問題排查的困難。是以我們需要對錯誤碼格式做定義。統一的錯誤碼有以下幾個優點。

  1. 一緻性和可維護性:微服務架構通常由多個服務組成,這些服務之間可能存在着複雜的調用關系。錯誤碼規範可以確定各個服務在處理錯誤時保持一緻性,統一使用相同的錯誤碼表示特定的錯誤類型。這樣可以提高項目的可維護性,降低代碼的複雜性,并使團隊成員更容易了解和處理錯誤。
  2. 故障排查和定位:在微服務架構中,由于服務之間的互相調用,錯誤可能會在多個服務之間傳播。如果每個服務都使用不同的錯誤碼表示相同的錯誤類型,将會給故障排查和定位帶來困難。錯誤碼規範可以提供一套統一的錯誤碼體系,使得定位故障點和排查問題更加高效。
  3. 可讀性和可了解性:錯誤碼規範可以提供有意義且易于了解的錯誤碼,使得開發人員、測試人員和運維人員能夠快速了解錯誤的原因和類型。這有助于團隊成員之間的溝通和協作,并降低解釋錯誤原因的時間和成本。
  4. 錯誤處理和容錯能力:通過錯誤碼規範,可以定義不同錯誤類型的處理政策和行為,例如重試、復原、降級等。這有助于實作系統的容錯能力,提高系統的穩定性和可靠性。
  5. 使用者體驗和錯誤回報:通過錯誤碼規範,可以提供統一的錯誤提示資訊,向使用者提供更友好和一緻的錯誤回報。使用者可以根據錯誤碼快速了解錯誤的原因,并采取相應的操作或尋求幫助。

代碼實作

類名:MessageCode

路徑:

platform-module/platform-module-starter/platform-module-starter-message/src/main/java/com/tinem/platform/module/starter/sdk/MessageCode.java           
package com.tinem.platform.module.starter.sdk;

import cn.hutool.core.util.StrUtil;
import lombok.Getter;

import java.util.*;

/**
 * @author fzh
 * @version v1
 * @program: platform
 * @className MessageCode
 * @description code 枚舉分段
 *                   下劃線【_】  為分段标志
 *                   中劃先【-】  為單詞标志
 *                   第一段【SUCCESS,ERROR】
 *                      SUCCESS 代表成功
 *                      ERROR 代表失敗
 *                   第二段【子產品名稱】
 *                      例如: PLATFORM-CLOUD-SERVICE-LINK
 *                   第三段【業務】
 *                   第四段【錯誤原因】
 * @site
 * @company
 * @create 2021-06-26 12:24
 */
@Getter
public class MessageCode {
    public final static List<MessageCode> MESSAGE_CODE_LIST = new ArrayList<>();

    /** 成功 */
    public final static MessageCode SUCCESS = new MessageCode("SUCCESS",new HashMap<Locale,String>(){{
        put(Locale.US,"success");
        put(Locale.SIMPLIFIED_CHINESE,"成功");
    }});

    /** 未知錯誤 */
    public final static MessageCode ERROR_COMMONS_UNKNOWN = new MessageCode("ERROR_COMMONS_UNKNOWN",new HashMap<Locale,String>(){{
        put(Locale.US,"system error:{0}");
        put(Locale.SIMPLIFIED_CHINESE,"系統錯誤:{0}");
    }});
    public final static MessageCode ERROR_COMMONS_404 = new MessageCode("ERROR_COMMONS_404",new HashMap<Locale,String>(){{
        put(Locale.US,"Service:{0}; Method:{1} is 404");
        put(Locale.SIMPLIFIED_CHINESE,"Service:{0}; Method:{1} is 404");
    }});
    public final static MessageCode ERROR_COMMONS_CLIENT_TIME = new MessageCode("ERROR_COMMONS_CLIENT_TIME",new HashMap<Locale,String>(){{
        put(Locale.US,"Client time error: {0}; Server time: {1}");
        put(Locale.SIMPLIFIED_CHINESE,"用戶端時間錯誤:{0}; 伺服器時間:{1}");
    }});
    /** 參數驗證失敗 */
    public final static MessageCode ERROR_COMMONS_REQUEST_REPEAT = new MessageCode("ERROR_COMMONS_REQUEST_REPEAT",new HashMap<Locale,String>(){{
        put(Locale.US,"Duplicate request:{0}");
        put(Locale.SIMPLIFIED_CHINESE,"請求重複:{0}");
    }});
    /** 參數驗證失敗 */
    public final static MessageCode ERROR_COMMONS_PARAMS = new MessageCode("ERROR_COMMONS_PARAMS",new HashMap<Locale,String>(){{
        put(Locale.US,"parameter validation failed:[{0}]");
        put(Locale.SIMPLIFIED_CHINESE,"參數驗證失敗:[{0}]");
    }});
    /** 參數驗證失敗 */
    public final static MessageCode ERROR_COMMONS_PARAMS_FIELD = new MessageCode("ERROR_COMMONS_PARAMS_FIELD",new HashMap<Locale,String>(){{
        put(Locale.US,"{0}");
        put(Locale.SIMPLIFIED_CHINESE,"{0}");
    }});
    /** 參數驗證失敗 */
    public final static MessageCode ERROR_COMMONS_SERVER = new MessageCode("ERROR_COMMONS_SERVER",new HashMap<Locale,String>(){{
        put(Locale.US,"server error:[{0}]");
        put(Locale.SIMPLIFIED_CHINESE,"服務異常:[{0}]");
    }});
    public final static MessageCode ERROR_COMMONS_ENCRYPTION_TYPE = new MessageCode("ERROR_COMMONS_ENCRYPTION_TYPE",new HashMap<Locale,String>(){{
        put(Locale.US,"Encryption type error, unrecognized encryption type");
        put(Locale.SIMPLIFIED_CHINESE,"加密類型錯誤,不識别的加密類型:{0}");
    }});
    public final static MessageCode ERROR_COMMONS_LIMIT_SENTINEL = new MessageCode("ERROR_COMMONS_LIMIT_SENTINEL",new HashMap<Locale,String>(){{
        put(Locale.US,"Request is restricted");
        put(Locale.SIMPLIFIED_CHINESE,"請求被限流");
    }});
    // -------------------------------------------------platform-cloud-service-user-------------------------------------
    public final static MessageCode ERROR_PLATFORM_CLOUD_SERVICE_USER_MOBILE = new MessageCode("ERROR_PLATFORM_CLOUD_SERVICE_USER_MOBILE",new HashMap<Locale,String>(){{
        put(Locale.US,"The mobile phone has been bound to other accounts");
        put(Locale.SIMPLIFIED_CHINESE,"手機已綁定其他賬号");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_SERVICE_USER_EMAIL = new MessageCode("ERROR_PLATFORM_CLOUD_SERVICE_USER_EMAIL",new HashMap<Locale,String>(){{
        put(Locale.US,"Email has been bound to other accounts");
        put(Locale.SIMPLIFIED_CHINESE,"郵箱已綁定其他賬号");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_SERVICE_USER_PASSWORD = new MessageCode("ERROR_PLATFORM_CLOUD_SERVICE_USER_PASSWORD",new HashMap<Locale,String>(){{
        put(Locale.US,"Password incorrect");
        put(Locale.SIMPLIFIED_CHINESE,"密碼錯誤");
    }});
    /** 未知錯誤 */
    public final static MessageCode ERROR_SESSION_NOT_FIND = new MessageCode("ERROR_SESSION_NOT_FIND",new HashMap<Locale,String>(){{
        put(Locale.US,"session not find");
        put(Locale.SIMPLIFIED_CHINESE,"會話不存在,請确認請求參數!");
    }});
    public final static MessageCode ERROR_SESSION_NOT_AUTHORIZE = new MessageCode("ERROR_SESSION_NOT_AUTHORIZE",new HashMap<Locale,String>(){{
        put(Locale.US,"Access to unauthorized url");
        put(Locale.SIMPLIFIED_CHINESE,"通路未授權url");
    }});
    public final static MessageCode ERROR_COUNTRY_BLACK_LIST = new MessageCode("ERROR_COUNTRY_BLACK_LIST",new HashMap<Locale,String>(){{
        put(Locale.US,"Your country has not opened services yet, please look forward to it!");
        put(Locale.SIMPLIFIED_CHINESE,"您所在的國家暫未開放服務,敬請期待!");
    }});
    // -------------------------------------------------platform-cloud-service-pay-------------------------------------
    public final static MessageCode ERROR_PLATFORM_CLOUD_SERVICE_ORDER_NOT_FIND = new MessageCode("ERROR_PLATFORM_CLOUD_SERVICE_ORDER_NOT_FIND",new HashMap<Locale,String>(){{
        put(Locale.US,"order id:{0},is not find.");
        put(Locale.SIMPLIFIED_CHINESE,"找到不訂單id:{0}.");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_SERVICE_ORDER_STATUS = new MessageCode("ERROR_PLATFORM_CLOUD_SERVICE_ORDER_STATUS",new HashMap<Locale,String>(){{
        put(Locale.US,"order id:{0},status:{1} is error.");
        put(Locale.SIMPLIFIED_CHINESE,"訂單{}狀态{}錯誤.");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_SERVICE_ORDER_EXPIRE = new MessageCode("ERROR_PLATFORM_CLOUD_SERVICE_ORDER_EXPIRE",new HashMap<Locale,String>(){{
        put(Locale.US,"order id:{0},status:{1} is expire.");
        put(Locale.SIMPLIFIED_CHINESE,"訂單{}狀态{}過期.");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_SERVICE_ORDER_PAY_ERROR = new MessageCode("ERROR_PLATFORM_CLOUD_SERVICE_ORDER_PAY_ERROR",new HashMap<Locale,String>(){{
        put(Locale.US,"order id:{0},pay:{1} is error.");
        put(Locale.SIMPLIFIED_CHINESE,"訂單{}支付失敗,原因:{1}.");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_SERVICE_ORDER_PAY_CHANNEL_NOT_FIND = new MessageCode("ERROR_PLATFORM_CLOUD_SERVICE_ORDER_PAY_CHANNEL_NOT_FIND",new HashMap<Locale,String>(){{
        put(Locale.US,"order pay channel:{0},is not find.");
        put(Locale.SIMPLIFIED_CHINESE,"找不到訂單支付管道:{0}.");
    }});
    // -------------------------------------------------platform-cloud-web-gateway--------------------------------------
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_GATEWAY_CLIENT_NOT_FIND = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_GATEWAY_CLIENT_NOT_FIND",new HashMap<Locale,String>(){{
        put(Locale.US,"403 forbidden client:[{0}]");
        put(Locale.SIMPLIFIED_CHINESE,"用戶端id錯誤:{0}");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_GATEWAY_SCOPE_NOT_FIND = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_GATEWAY_SCOPE_NOT_FIND",new HashMap<Locale,String>(){{
        put(Locale.US,"403 forbidden scope:[{0}]");
        put(Locale.SIMPLIFIED_CHINESE,"用戶端權限不足,無法通路:[{0}]");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_GATEWAY_SIGN_TYPE = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_GATEWAY_SIGN_TYPE",new HashMap<Locale,String>(){{
        put(Locale.US,"Request signature type mismatch");
        put(Locale.SIMPLIFIED_CHINESE,"請求簽名類型不比對.用戶端需要簽名類型:{0}; 上傳簽名類型: {1}");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_GATEWAY_SIGN = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_GATEWAY_SIGN",new HashMap<Locale,String>(){{
        put(Locale.US,"Request signature mismatch");
        put(Locale.SIMPLIFIED_CHINESE,"請求簽名不比對.");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_GATEWAY_CRYPTO_TYPE = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_GATEWAY_CRYPTO_TYPE",new HashMap<Locale,String>(){{
        put(Locale.US,"The requested encryption type does not match,{},{}");
        put(Locale.SIMPLIFIED_CHINESE,"請求加密類型不比對.用戶端需要加密類型:{0}; 上傳加密類型: {1}");
    }});

    // -------------------------------------------------platform-cloud-web-auth-----------------------------------------

    public final static MessageCode VERIFICATION_CODE_VALID_FOR_FIVE_MINUTES = new MessageCode("VERIFICATION_CODE_VALID_FOR_FIVE_MINUTES",new HashMap<Locale,String>(){{
        put(Locale.US,"The email verification code is valid for {0} minutes. Do not apply for multiple verification codes");
        put(Locale.SIMPLIFIED_CHINESE,"郵箱驗證碼{0}分鐘有效,請勿多次發送");
    }});

    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_AUTH_CODE = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_AUTH_CODE",new HashMap<Locale,String>(){{
        put(Locale.US,"Mailbox verification code error");
        put(Locale.SIMPLIFIED_CHINESE,"郵箱驗證碼錯誤");
    }});
    public final static MessageCode THE_GRAPHIC_VERIFICATION_CODE_IS_INCORRECT = new MessageCode("THE_GRAPHIC_VERIFICATION_CODE_IS_INCORRECT",new HashMap<Locale,String>(){{
        put(Locale.US,"Graphic verification code error");
        put(Locale.SIMPLIFIED_CHINESE,"圖形驗證碼錯誤");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_AUTH_CODE_IMAGE = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_AUTH_CODE_IMAGE",new HashMap<Locale,String>(){{
        put(Locale.US,"Please fill in the picture verification code");
        put(Locale.SIMPLIFIED_CHINESE,"請填寫圖檔驗證碼");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_AUTH_CODE_TO = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_AUTH_CODE_TO",new HashMap<Locale,String>(){{
        put(Locale.US,"Unrecognized receiver, please enter email or mobile phone number");
        put(Locale.SIMPLIFIED_CHINESE,"不能識别的接收方,請輸入郵箱或者手機号");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_AUTH_CLIENT_IP = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_AUTH_CODE_TO",new HashMap<Locale,String>(){{
        put(Locale.US,"Client IP is not in the whitelist");
        put(Locale.SIMPLIFIED_CHINESE,"用戶端IP不在白名單");
    }});

    // -------------------------------------------------platform-cloud-web-websocket------------------------------------
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_WEBSOCKET_SESSION_NOT_FIND = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_WEBSOCKET_SESSION_NOT_FIND",new HashMap<Locale,String>(){{
        put(Locale.US,"success");
        put(Locale.SIMPLIFIED_CHINESE,"未找到session:{0}");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_WEBSOCKET_CONNECTION_STATUS_IS_NOT_CONNECTION = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_WEBSOCKET_CONNECTION_STATUS_IS_NOT_CONNECTION",new HashMap<Locale,String>(){{
        put(Locale.US,"success");
        put(Locale.SIMPLIFIED_CHINESE,"連結未初始化");
    }});

    // -------------------------------------------------platform-cloud-web-file------------------------------------

    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_FILE_GENERATION_FAILED = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_FILE_GENERATION_FAILED",new HashMap<Locale,String>(){{
        put(Locale.US,"File generation failed");
        put(Locale.SIMPLIFIED_CHINESE,"檔案生成失敗");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_FILE_SIZE_LIMIT = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_FILE_SIZE_LIMIT",new HashMap<Locale,String>(){{
        put(Locale.US,"File generation failed");
        put(Locale.SIMPLIFIED_CHINESE,"目前檔案大小超過限制");
    }});
    public final static MessageCode ERROR_PLATFORM_CLOUD_WEB_STORAGE_SIZE_LIMIT = new MessageCode("ERROR_PLATFORM_CLOUD_WEB_STORAGE_SIZE_LIMIT",new HashMap<Locale,String>(){{
        put(Locale.US,"File generation failed");
        put(Locale.SIMPLIFIED_CHINESE,"管道存儲空間不足");
    }});

    String name;
    Map<Locale,String> localMessage;

    public MessageCode(String name,Map<Locale,String> localMessage){
        this.name = name;
        this.localMessage = localMessage;
        MESSAGE_CODE_LIST.add(this);
    }

    public static List<MessageCode> values(){
        return MESSAGE_CODE_LIST;
    }
    public static MessageCode valueOf(String name){
        Optional<MessageCode> messageCode = MESSAGE_CODE_LIST.stream().filter(mc -> mc.name().equalsIgnoreCase(name)).findFirst();
        if(messageCode.isPresent()){
            return messageCode.get();
        }
        throw new IllegalArgumentException("No enum "+name);
    }

    public String name(){return name;};


    public String getMessage(Locale locale,Object... params){
        if(locale == null){
            locale = Locale.US;
        }
        return StrUtil.indexedFormat(localMessage.containsKey(locale) ? localMessage.get(locale) : localMessage.get(Locale.US),params);
    }
    public String getMessage(Object... params){
        return getMessage(Locale.US,params);
    }

}           

在我們定義好錯誤碼後再代碼中使用

UserException代表由使用者引起的異常,例如參數錯誤,通路一個不存在的資源等。

SystemException代表系統錯誤,例如資料庫連結失敗,網絡錯誤,記憶體溢出等。

微服務項目錯誤碼規範和多語言的錯誤消息

這兩個異常都有一個構造函數,第一個參數是錯誤碼,第二個參數是錯誤消息中的參數。

微服務項目錯誤碼規範和多語言的錯誤消息
微服務項目錯誤碼規範和多語言的錯誤消息
微服務項目錯誤碼規範和多語言的錯誤消息

Postman測試

這裡我們用一個錯誤的用戶端時間發送請求,然後分别切換語言為中文和英文,檢視網關傳回的錯誤消息。

  1. 英文
微服務項目錯誤碼規範和多語言的錯誤消息
微服務項目錯誤碼規範和多語言的錯誤消息
  1. 中文
微服務項目錯誤碼規範和多語言的錯誤消息
微服務項目錯誤碼規範和多語言的錯誤消息

繼續閱讀