Maison  >  Article  >  Java  >  Meilleure façon de gérer la localisation des messages d'exception dans Spring Boot

Meilleure façon de gérer la localisation des messages d'exception dans Spring Boot

WBOY
WBOYoriginal
2024-09-06 06:03:02363parcourir

Best Way to Handle Localization For Exception Messages in Spring Boot

À mesure que les applications se développent pour servir un public mondial, la localisation devient un aspect crucial du développement logiciel. La localisation permet aux applications de s'adapter à différentes langues et régions, offrant ainsi une expérience conviviale. 

Dans cet article, je vais partager ma façon préférée de gérer les exceptions localisées dans une application Spring Boot.

Pourquoi avons-nous besoin d’une localisation pour les messages d’exception ?

La localisation des messages d'exception côté backend est essentielle pour créer une expérience utilisateur transparente, en particulier dans les applications ciblant un public mondial. 

En localisant ces messages sur le backend et en les envoyant directement au frontend, nous pouvons prendre la responsabilité de gérer plusieurs langues hors des épaules des développeurs frontend. Cette approche garantit que les messages d'erreur sont cohérents sur toutes les plates-formes et toutes les langues, permettant aux développeurs frontend de se concentrer sur l'affichage de ces messages de manière conviviale, comme dans un toast d'erreur. 

En conséquence, l'interface n'a pas besoin de gérer des messages d'exception personnalisés pour chaque langue, ce qui réduit la duplication des efforts et le risque d'erreurs, et garantit que tous les utilisateurs reçoivent des commentaires clairs et pertinents dans leur langue préférée.

Comment atteindre facilement notre objectif dans le backend ?

Suivez les étapes ci-dessous pour atteindre notre objectif. 

Classe d'exception générale

Commencez par créer une classe qui s'étend de RuntimeException et nommez-la ResponseException. Cette exception personnalisée vous permettra de gérer les erreurs spécifiques à l'application de manière plus contrôlée.

public class ResponseException extends RuntimeException {

}

Classe d'erreur de réponse

Créez une classe distincte qui sera renvoyée dans la réponse lorsqu'une exception se produit. Cette classe peut contenir des champs tels que message, horodatage, errorCode et toute autre information pertinente que vous souhaitez transmettre au frontend.

public record ErrorResponse(int status, String message) {

}

Gestionnaire d’exceptions globales

Implémentez un GlobalExceptionHandler à l'aide de l'annotation @ControllerAdvice de Spring. Dans cette classe, vous pouvez intercepter la ResponseException et la mapper au message localisé approprié en fonction des paramètres régionaux de l'utilisateur.

@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());
  }
}

Fichiers de propriétés spécifiques à une langue

Pour gérer les messages localisés, créez des fichiers de propriétés pour chaque langue prise en charge, tels que messages_en.properties pour l'anglais, messages_az.properties pour l'azerbaïdjanais, etc. Ces fichiers contiendront les paires clé-valeur pour chaque message d'exception, permettant à Spring de résoudre automatiquement le message correct en fonction des paramètres régionaux de l'utilisateur.

Créez ces fichiers de propriétés dans le dossier src/main/resources.

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

Implémenter la partie localisation

J'ai créé le strict minimum pour gérer les exceptions dans Spring Boot. Je suppose que vous connaissez déjà ce qui précède. Continuons à ajouter une partie de traduction.

Modifier la classe 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);
  }  
}

Créez des méthodes d'assistance pour les codes HttpStatus fréquemment utilisés tels que NOT_FOUND, FORBIDDEN.

Vous pouvez utiliser ces méthodes d'assistance de la manière suivante :

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

Créez un modèle de message user_not_found dans tous vos fichiers de propriétés.

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

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

Afin de les remplacer automatiquement avant de revenir au frontend, mettez à jour la méthode dans la classe 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());
  }
}

Comment utiliser des valeurs dynamiques dans les messages d'exception

Cette façon de gérer les exceptions est utile, vous devez notamment définir des valeurs dynamiques pour vos messages d'exception. Par exemple,

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

Afin de remplacer {0} par une valeur dynamique.

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

J'ai mis le paramètre varargs à la fin pour transmettre plusieurs paramètres dynamiques sans créer de nouvelle méthode à chaque fois.

J'ai un article dédié sur les messages avec des valeurs dynamiques.

Où obtenir les paramètres régionaux de l'utilisateur ?

J'ai deux approches pour obtenir les paramètres régionaux :

  1. Paramètres régionaux des utilisateurs stockés dans la base de données en fonction des préférences de l'interface utilisateur.

  2. Certaines méthodes de contrôleur acceptent le paramètre de requête de langue facultatif. Cela peut être utile pour tester lorsque les développeurs frontend souhaitent voir à quoi ressemblera l'interface utilisateur dans différentes langues. Parce que la longueur des phrases dans chaque langue n'est pas la même.

Conclusion

C'est tout pour aujourd'hui. J'espère que vous avez apprécié.

Le code source est disponible sur le référentiel de mon compte GitHub.

Si vous avez des questions, n'hésitez pas à me contacter via LinkedIn.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn