首頁  >  文章  >  Java  >  在 Spring Boot 中處理異常訊息本地化的最佳方法

在 Spring Boot 中處理異常訊息本地化的最佳方法

WBOY
WBOY原創
2024-09-06 06:03:02360瀏覽

Best Way to Handle Localization For Exception Messages in Spring Boot

隨著應用程式不斷發展以服務全球受眾,在地化成為軟體開發的重要方面。在地化允許應用程式適應不同的語言和地區,提供用戶友好的體驗。 

在本文中,我將分享我最喜歡的在 Spring Boot 應用程式中處理本地化異常的方法。

為什麼我們需要對異常訊息進行在地化?

後端異常訊息的在地化對於創建無縫的用戶體驗至關重要,尤其是在面向全球受眾的應用程式中。 

透過在後端本地化這些訊息並將它們直接發送到前端,我們可以從前端開發人員的肩上承擔管理多種語言的責任。這種方法可確保錯誤訊息在所有平台和語言中保持一致,從而使前端開發人員能夠專注於以使用者友好的方式(例如在錯誤 toast 中)顯示這些訊息。 

因此,前端無需處理每種語言的自訂異常訊息,從而減少了重複工作和潛在的錯誤,並確保所有使用者都以其首選語言收到清晰且相關的回饋。

後端如何方便的實現我們的目標呢?

請按照以下步驟來實現我們的目標。 

一般異常類

首先建立一個從 RuntimeException 擴展的類,並將其命名為 ResponseException。此自訂異常將允許您以更受控的方式處理特定於應用程式的錯誤。

public class ResponseException extends RuntimeException {

}

回應錯誤類別

建立一個單獨的類,當發生異常時,該類將在回應中傳回。此類別可以包含訊息、時間戳記、錯誤代碼等欄位以及您想要傳遞給前端的任何其他相關資訊。

public record ErrorResponse(int status, String message) {

}

全域異常處理程序

使用 Spring 的 @ControllerAdvice 註解實作 GlobalExceptionHandler。在此類中,您可以捕獲 ResponseException 並根據使用者的區域設定將其對應到適當的本地化訊息。

@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

  @ExceptionHandler(value = ResponseException.class)
  public ResponseEntity<ErrorResponse> handleResponseStatusException(
      ResponseException ex
  ) {
    log.error("ResponseException: {}", ex.getMessage());

    String message = ex.getMessage();

    var errorResponse = new ErrorResponse(ex.getStatus().value(), message);

    return new ResponseEntity<>(errorResponse, ex.getStatus());
  }
}

特定於語言的屬性文件

要管理本地化訊息,請為每種支援的語言建立屬性文件,例如英文的 messages_en.properties、阿塞拜疆語的 messages_az.properties 等。這些檔案將包含每個異常訊息的鍵值對,允許 Spring 根據使用者的區域設定自動解析正確的訊息。

在 src/main/resources 資料夾中建立這些屬性檔案。

err.username_already_exists.msg=User with username: {0} is already exists.

實施本地化部分

我已經創建了在 Spring Boot 中處理異常的最低限度。我想你已經熟悉上面的內容了。我們繼續新增翻譯部分。

修改ResponseException類別:

public class ResponseException extends RuntimeException {
  private final String messageTemplate;
  private final transient Object[] params;
  private final Locale locale;

  public static ResponseException notFound(String messageTemplate, Locale locale) {
    return new ResponseException(HttpStatus.NOT_FOUND, messageTemplate, null, locale);
  }

  public static ResponseException notFound(String messageTemplate, Object[] params, Locale locale) {
    return new ResponseException(HttpStatus.NOT_FOUND, messageTemplate, params, locale);
  }

  public static ResponseException forbidden(String messageTemplate, Locale locale) {
    return new ResponseException(HttpStatus.FORBIDDEN, messageTemplate, null, locale);
  }

  public static ResponseException forbidden(String messageTemplate, Object[] params, Locale locale) {
    return new ResponseException(HttpStatus.FORBIDDEN, messageTemplate, params, locale);
  }  
}

為常用的 HttpStatus 程式碼建立輔助方法,例如 NOT_FOUNDFORBIDDEN.

您可以透過以下方式使用這些輔助方法:

// some code parts omitted ...
userService.findByUsername(username)
  .orElseThrow(() -> ResponseException.notFound("user_not_found", locale))

在所有屬性檔案中建立 user_not_found 訊息範本。

// file: messages_en.properties
user_not_found=User not found

// file: messages_az.properties
user_not_found=İsdifadəçi tapılmadı

為了在傳回前端之前自動取代這些,請更新 GlobalExceptionHandler 類別中的方法。

@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

  private final MessageSource messageSource;

  @ExceptionHandler(value = ResponseException.class)
  public ResponseEntity<ErrorResponse> handleResponseStatusException(
      ResponseException ex
  ) {
    log.error("ResponseException: {}", ex.getMessage());

    String message = ex.getMessage();

    String messageTemplate = ex.getMessageTemplate();
    if (StringUtils.isNotBlank(messageTemplate)) {
      message = messageSource.getMessage(messageTemplate, ex.getParams(), ex.getLocale());
    }

    var errorResponse = new ErrorResponse(ex.getStatus().value(), message);

    return new ResponseEntity<>(errorResponse, ex.getStatus());
  }
}

如何在異常訊息中使用動態值

這種處理異常的方法非常有用,特別是您必須為異常訊息設定動態值。例如,

// file: messages_en.properties
err.invalid_phone_number.msg=The phone: {0} is invalid

為了用動態值取代 {0}。

public static ResponseException badRequest(
      String messageTemplate, 
      Locale locale,
      String... params
) {
  return new ResponseException(
        HttpStatus.BAD_REQUEST, 
        messageTemplate, 
        params, 
        locale
  );
}

我將 varargs 參數放在最後以傳遞多個動態參數,而無需每次都建立新方法。

我有一篇關於具有動態值的消息的專門文章。

從哪裡取得使用者的區域設定?

我有兩種取得語言環境的方法:

  1. 根據 UI 首選項儲存在資料庫中的使用者區域設定。

  2. 一些控制器方法接受可選的 lang 請求參數。當前端開發人員想要查看 UI 在不同語言中的表現時,這對於測試可能很有用。因為每種語言的句子長度都不一樣。

結論

今天就到此為止。我希望你喜歡。

原始程式碼可在我的 GitHub 帳戶的儲存庫中找到。

如果您有任何疑問,請隨時透過 LinkedIn 與我聯繫。

以上是在 Spring Boot 中處理異常訊息本地化的最佳方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn