Write it down while it’s hot for your future self

The foreword 0.

Uniform design and specification of the use of error codes in a project and throughout the development of the entire team is a point that must be implemented.

The design of error codes is directly related to the organization and elegance of back-end interfaces. The use of error codes is directly related to the development standards and efficiency of developers.

Therefore, the elegant management of error codes is very necessary and is one of the cornerstones of a team.

Below, I will elaborate one by one from three aspects: how to design, manage and implement multi-language error codes.

1. The design

First of all, there are roughly two types of right and wrong codes:

  • Universal error code
  • Special Meaning Error code

Secondly, the error code needs to contain the following elements:

  • Error code
  • Chinese error message
  • English error message

1.1 Common Error Code

Includes: success and failure (unknown error)

  • SUCCESS(“10000”, “success “,” OK”),
  • UNKNOWN_ERROR(“-1”, “unknown error”, “unknown error”)

1.2 Special Meanings Error code

  • User-related errors such as:

A_PARAM_VALIDATION_ERROR(“A0100”, “parameter validation error”, “parameter Validation error”)

  • Errors related to third party dependencies such as:

B_STORAGE_ERROR(“B0100”, “persistent storage error”, “storage error”)

  • Errors related to the current business system, such as:

C_RESOURCE_OUT_ERROR(“C0100”, “system resource error”, “system resource error”)

2. Management

At present, there is no human input into the development of error code management platform, and there is no suitable open source project to use in the market. Therefore, we temporarily use the flying book document to do error code management. A little.

3. Implementation

On the code side, you first have an enumerated class to hold all the error codes.

Error code enumeration class

Public enum ReturnEnum {/** * succeeded */ SUCCESS("10000", "succeeded "," OK "), /** * unknown error */ UNKNOWN_ERROR("-1", "UNKNOWN_ERROR ", "Unknown error"), /** * Level 1 macro error code, user related */ A_USER_CLIENT_ERROR("A0000"," client error", "user client error"), /** * Level 1 macro error code, Related to third party services: */ B_GENERAL_3RD_ERROR("B0000", "general 3rd error"), /** * secondary macro error code, persistent storage error, */ B_STORAGE_ERROR("B0100", "persistent storage error", "storage error"), B_SQL_INTEGRITY_CONSTRAINT_VIOLATION_ERROR("B0101", "SQL integrity constraint VIOLATION"), B_DUPLICATE_KEY_ERROR("B0102", "error with unique database index constraint "," DUPLICATED key"), B_QUERY_NO_RESULT("B0103", "No data is checked ", "No Data queried"), B_MINIO_UPLOAD_URL_ERROR("B0104"," Get upload file URL error"), /** * Cache storage error, Mainly related to redis */ B_CACHE_ERROR("B0200", "cache error", "cache error"), B_CACHE_REDIS_SET_ERROR("B0201", "cache write exception ", "Cache set error"), B_CACHE_REDIS_DEL_ERROR("B0202", "cache del error", "cache del error"), B_CACHE_REDIS_GET_ERROR("B0203", "cache get error", "cache get error"), /** * Related to third-party interfaces */ B_3RD_API_ERROR("B0300", "3rd API error"), /** * Level 1 macro error code, related to the current system: / C_GENERAL_BUSINESS_ERROR("B0000", "general Business error", "general Business error"), /**; String msgCode; String msgCn; String msgEn; }Copy the code

Added a LanguageInterceptor

public class LanguageInterceptor implements HandlerInterceptor {
 @Override
    public boolean preHandle ( HttpServletRequest request, HttpServletResponse response, Object handler ) throws Exception {
     String acceptLanguage = request.getHeader ( HttpHeaders.ACCEPT_LANGUAGE) ;
     RequestHolderUtil.addLang( acceptLanguage ) ;
     return true;
    }

 @Override
    public void postHandle ( HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView ) throws Exception {

 }

 @Override
    public void afterCompletion ( HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex ) throws Exception {
         RequestHolderUtil.remove() ;
    }
 }

public class RequestHolderUtil {
    private static final ThreadLocal<String> requestHolder = new ThreadLocal();
    public RequestHolderUtil() {
    }

    public static void addLang(String language) {
        requestHolder.set(language);
    }

    public static String getLang() {
        return (String)requestHolder.get();
    }

    public static void remove() {
        requestHolder.remove();
    }

}
Copy the code

Register interceptors

@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors ( InterceptorRegistry registry ) { registry.addInterceptor ( new LanguageInterceptor ()) .addPathPatterns ( "/**" ) ; }}Copy the code

Return to wrapper class

@Data @AllArgsConstructor @Slf4j public class ReturnBase implements Serializable { private static final long serialVersionUID = 1L; Public static final String TRACE_ID = "TRACE_ID"; private String traceId; private String msgCode; private String msg; private Object data; private Integer total; . public static ReturnBase error ( ReturnEnum returnEnum ) { return error( returnEnum, RequestHolderUtil.getLang()) ; } public static ReturnBase error(ReturnEnum returnEnum, String language) { String msg; if (Objects.isNull(language)) { return new ReturnBase(MDC.get(TRACE_ID), returnEnum.getMsgCode(), returnEnum.getMsgEn(), null, 0); } switch(language){ case CommonConstant.SIMPLE_CHINESE: msg = returnEnum.getMsgCn(); break; default: msg = returnEnum.getMsgEn(); break; } return new ReturnBase(MDC.get(TRACE_ID), returnEnum.getMsgCode(), msg, null, 0); }... public static String MsgFormat ( String code, String msg ) { return String.format( "%s (error: %s)", msg, code ) ; }}Copy the code

Use the sample

‘ ‘ACCEPT_LANGUAGE’ ‘= zh-hans;

After intercepting the backend LanguageInterceptor, the ACCEPT_LANGUAGE is inserted into the Threadlocal* variable of the current request.

The back end returns an error code to the front end: returnBase. error(‘ ReturnEnum ‘. ‘C_GENERAL_BUSINESS_ERROR’); In the returnBase.error () method, Chinese or English error text is automatically selected to return based on the ACCEPT_LANGUAGE variable previously inserted into Threadlocal.