mardi 12 septembre 2023

[Spring Boot] la propriété spring.main.web-application-type

En Spring Boot, la propriété spring.main.web-application-type est utilisée pour définir le type d'application web que vous souhaitez créer. Cette propriété peut avoir l'une des trois valeurs suivantes :


none : Cela signifie qu'aucune application web n'est activée. Cela convient aux applications Spring Boot qui ne sont pas destinées à être des applications web, par exemple, les applications de ligne de commande ou les applications de traitement de fond.


servlet : Cela indique que vous souhaitez créer une application web basée sur le Servlet. Cette option est appropriée pour la création d'applications web traditionnelles qui utilisent le conteneur de servlets Java pour gérer les requêtes HTTP. Vous pouvez utiliser des annotations comme @Controller et @RequestMapping pour créer des contrôleurs web dans ce mode.


reactive : Cela indique que vous souhaitez créer une application web réactive. Lorsque vous choisissez cette option, Spring Boot utilise le paradigme de programmation réactive pour gérer les requêtes HTTP. Cela convient aux applications qui doivent gérer un grand nombre de requêtes simultanées et qui souhaitent bénéficier de la réactivité pour une meilleure évolutivité.


Par exemple, si vous définissez spring.main.web-application-type dans votre fichier application.yml comme suit :

application.yml
spring:    
    main: 
        web-application-type: servlet

Cela signifie que vous créez une application web basée sur le Servlet.


En résumé, la propriété spring.main.web-application-type permet de définir le type d'application web que vous souhaitez créer avec Spring Boot, que ce soit une application non web, une application basée sur Servlet ou une application réactive. 

Source : https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html 

lundi 11 septembre 2023

[JAVA 17] Simplifiez la Manipulation de Données en Java avec le Pattern Matching

Introduction :

Le pattern matching est une fonctionnalité puissante introduite dans Java à partir de la version 14. Faisant partie du projet Amber, son objectif est d'améliorer la productivité des développeurs Java en introduisant de nouvelles fonctionnalités de langage. Dans cet article, nous allons explorer le pattern matching et ses différentes formes, tout en fournissant des exemples concrets pour illustrer son utilisation.


Le Pattern Matching pour instanceof :

Le pattern matching pour instanceof est la première forme de pattern matching introduite dans Java. Il simplifie la vérification de types pour les objets. Avant cela, pour vérifier si un objet était d'un certain type, il fallait utiliser l'opérateur instanceof et ensuite effectuer un cast de l'objet pour accéder à ses propriétés. Voici un exemple de code pour illustrer cette simplification :


Avant le pattern matching :

if (obj instanceof String) { String str = (String) obj; // Utilisation de str }

Après le pattern matching :

if (obj instanceof String str) { // Utilisation de str }

Le Pattern Matching pour switch :

Le pattern matching pour switch est une autre forme de pattern matching introduite dans Java. Il simplifie la vérification de plusieurs conditions pour une variable donnée. Voici un exemple comparant l'utilisation traditionnelle du switch avec le pattern matching :

Utilisation traditionnelle du switch :

switch (dayOfWeek) { case MONDAY: case TUESDAY: case WEDNESDAY: System.out.println("C'est un jour de travail !"); break; default: System.out.println("C'est le week-end !"); break; }

Utilisation du pattern matching pour switch :


switch (dayOfWeek) { case MONDAY, TUESDAY, WEDNESDAY -> System.out.println("C'est un jour de travail !"); default -> System.out.println("C'est le week-end !"); }

Le Pattern Matching avec les Records :

Les records, introduits à partir de Java 16, simplifient la définition de classes en fournissant une syntaxe concise et des méthodes générées automatiquement pour accéder aux propriétés de l'objet. Les record patterns permettent d'utiliser les records avec le pattern matching. Voici un exemple de record et son utilisation avec le pattern matching :


Définition d'un record :


record Person(String name, int age) {}

Utilisation du record avec le pattern matching :


if (obj instanceof Person person) { System.out.println("Nom : " + person.name() + ", Age : " + person.age()); }

Résumé :

En résumé, le pattern matching est une fonctionnalité importante introduite dans Java pour simplifier la manipulation de données complexes et rendre le code plus lisible et compréhensible. Il offre une approche plus simple et plus efficace pour la vérification des types, la simplification des switch, l'utilisation des records, et bien plus encore. En utilisant des exemples concrets, nous avons exploré comment cette fonctionnalité améliore la productivité des développeurs Java. N'hésitez pas à l'adopter pour rendre votre code plus élégant et maintenable.


dimanche 10 septembre 2023

[Spring ] Quelle est la différence entre bean factory et application contexte?

Le contenueur IoC Spring, founri le BeanFactory et l'ApplicationContext qui sont deux interfaces clés pour la gestion et l'accès aux beans. Voici les différences entre les deux :


BeanFactory :


Lazy Initialization : Le BeanFactory est le conteneur de base pour la gestion des beans. Il offre une gestion paresseuse (lazy) des beans, ce qui signifie que les beans ne sont instanciés qu'au moment de leur première utilisation. Cela peut être plus efficace en termes de ressources, car les beans ne sont créés qu'en cas de nécessité.


Plus Léger : Le BeanFactory est plus léger en termes de ressources car il ne charge pas tous les beans immédiatement lors du démarrage de l'application.


Fonctionnalité Limitée : Le BeanFactory offre les fonctionnalités de base de la gestion des beans, telles que la création, la configuration et la fourniture de beans, mais il ne prend en charge que les fonctionnalités essentielles.


Utilisation Explicit : Pour utiliser un BeanFactory, vous devez le configurer explicitement dans votre application.


ApplicationContext :


Eager Initialization : L'ApplicationContext est une surcouche du BeanFactory et offre toutes ses fonctionnalités. Cependant, il initialise les beans de manière anticipée (eagerly) lors du démarrage de l'application, à moins que vous ne configuriez explicitement le contexte pour une initialisation paresseuse.


Riche en Fonctionnalités : L'ApplicationContext est plus riche en fonctionnalités que le BeanFactory. Il prend en charge des fonctionnalités avancées telles que l'injection de dépendances automatique, la gestion des transactions, l'internationalisation, la gestion des événements, etc.


Utilisation Courante : L'ApplicationContext est largement utilisé dans la plupart des applications Spring en raison de sa richesse en fonctionnalités et de sa commodité.


Utilisation Facilitée : Vous pouvez obtenir un ApplicationContext en utilisant une variété de classes de configuration, telles que AnnotationConfigApplicationContext, ClassPathXmlApplicationContext, etc., ce qui rend son utilisation plus facile.

Exemple :

var context = new AnnotationConfigApplicationContext(ClasseConfiguration.class);


Pour récupérer un bean géré par le conteneur IoC (Inversion of Control) de Spring, vous pouvez utiliser l'application du contexte (application context) de Spring :


var classe= (Classe) context.getBean("classe");


En résumé, l'ApplicationContext est une extension plus puissante du BeanFactory et est largement utilisé dans les applications Spring modernes en raison de ses fonctionnalités étendues et de sa facilité d'utilisation. Cependant, si vous avez besoin d'une gestion paresseuse des beans et que vous souhaitez économiser des ressources en initialisant les beans uniquement lorsque cela est nécessaire, vous pouvez opter pour le BeanFactory.

mercredi 12 avril 2023

L'impact de l'annotation @EqualsAndHashCode de Lombok sur le dirty checking de JPA \ Hibernate.

 Lombok est une bibliothèque Java qui permet de simplifier l'écriture de code en fournissant des annotations pour générer automatiquement du code répétitif. L'une de ces annotations est @EqualsAndHashCode, qui génère automatiquement les méthodes equals() et hashCode() pour une classe Java.


Cependant, lorsqu'on utilise l'annotation @EqualsAndHashCode avec JPA Hibernate, cela peut avoir un impact sur le dirty checking de JPA Hibernate, qui est un mécanisme utilisé pour détecter les changements apportés à une entité et pour les enregistrer dans la base de données.


Dirty checking avec JPA Hibernate

Avant de comprendre l'impact de l'annotation @EqualsAndHashCode sur le dirty checking de JPA Hibernate, il est important de comprendre comment fonctionne le dirty checking dans JPA Hibernate.


Lorsqu'on utilise JPA Hibernate, les entités sont suivies en permanence par le framework. Cela signifie que lorsque l'on charge une entité depuis la base de données, Hibernate garde une copie de cette entité en mémoire. Lorsque l'on apporte des modifications à cette entité, Hibernate compare la copie en mémoire avec l'entité modifiée pour détecter les changements.


Cette comparaison se fait via la méthode equals() de l'entité. Si les deux instances de l'entité sont égales, cela signifie que l'entité n'a pas été modifiée et qu'il n'est pas nécessaire de la sauvegarder dans la base de données. En revanche, si les deux instances de l'entité sont différentes, cela signifie qu'il y a eu des changements et que l'entité doit être sauvegardée dans la base de données.


L'impact de @EqualsAndHashCode sur le dirty checking

Lorsqu'on utilise l'annotation @EqualsAndHashCode avec JPA Hibernate, cela peut avoir un impact sur le dirty checking de JPA Hibernate. En effet, l'annotation @EqualsAndHashCode génère automatiquement les méthodes equals() et hashCode() pour une classe Java en se basant sur les champs de la classe. Si un champ de la classe est modifié, la méthode equals() générée par l'annotation considérera que l'instance de l'entité a changé, même si le champ modifié n'a pas d'impact sur l'état de l'entité dans la base de données.


Par exemple, si une entité "Client" a un champ "nom" et que l'on utilise l'annotation @EqualsAndHashCode pour générer la méthode equals(), si l'on modifie le champ "nom", la méthode equals() considérera que l'instance de l'entité a changé, même si ce changement n'a aucun impact sur l'état de l'entité dans la base de données.


Dans ce cas, le dirty checking de JPA Hibernate va détecter ce changement et va enregistrer l'entité modifiée dans la base de données, même si cela n'est pas nécessaire.


Les attributs à exclure de @EqualsAndHashCode

Pour éviter cet impact sur le dirty checking de JPA Hibernate, il est recommandé d'exclure certains attributs de la méthode equals() générée par l'annotation @EqualsAndHashCode.


Les attributs à exclure de la méthode equals() sont ceux qui n'ont pas d'impact sur l'état de l'entité dans la base de données. Ces attributs peuvent être des valeurs dérivées d'autres attributs, des attributs utilisés uniquement pour l'affichage, ou des attributs de configuration qui ne sont pas stockés dans la base de données.


Par exemple, pour une entité "Client" qui a un champ "nom" et un champ "adresse", si l'on veut exclure l'adresse de la méthode equals(), on peut utiliser l'annotation @EqualsAndHashCode.Exclude pour exclure le champ "adresse" de la méthode equals() :

@Data

@Entity

@EqualsAndHashCode(exclude={"adresse"})

public class Client {

    @Id

    @GeneratedValue(strategy = GenerationType.AUTO)

    private Long id;

    private String nom;

    private String adresse;

    // ...

}


Ainsi, si l'on modifie le champ "adresse", la méthode equals() ne considérera pas que l'instance de l'entité a changé, et le dirty checking de JPA Hibernate ne détectera pas de changement.

Le champ "id" d'une entité est une clé de base de données, et ne devrait pas être une préoccupation de la logique métier. Pour que le contrat equals et hashCode de l'entité soit valide quel que soit l'état de l'entité, il est recommandé d'utiliser l'annotation @EqualsAndHashCode.Exclude sur le champ "id" et sur les champs bidirectionnels relatifs aux adresses.

Enfin, lors de l'utilisation de la méthode toString, il est important de séparer les préoccupations, et d'exclure les champs bidirectionnels pour éviter un débordement de pile potentiel si on essaye d'imprimer l'objet. Pour cela, on peut utiliser l'annotation @ToString.Exclude sur chaque champ bidirectionnel.

Conclusion

L'utilisation de l'annotation @EqualsAndHashCode de Lombok peut simplifier l'écriture de code en générant automatiquement les méthodes equals() et hashCode() pour une classe Java. Cependant, lorsqu'on utilise cette annotation avec JPA Hibernate, il est important de faire attention à l'impact sur le dirty checking de JPA Hibernate.


Pour éviter cet impact, il est recommandé d'exclure certains attributs de la méthode equals() générée par l'annotation @EqualsAndHashCode. Ces attributs sont ceux qui n'ont pas d'impact sur l'état de l'entité dans la base de données. En excluant ces attributs, on peut éviter que le dirty checking de JPA Hibernate détecte des changements inutiles et améliorer les performances de notre application.


jeudi 16 mars 2023

[Java 11] Gestion de plusieurs formats de date en Java avec DateTimeFormatterBuilder

Introduction

Lorsqu’on travaille avec des dates en Java, il est souvent nécessaire de gérer plusieurs formats de date différents. Cela peut être dû au fait que les utilisateurs peuvent entrer des dates dans différents formats, ou que les données sont fournies par des sources externes dans des formats variés. Sans une gestion appropriée de ces formats, il peut être difficile de manipuler les dates correctement et cela peut entraîner des erreurs dans l’application.

Problème

La gestion de plusieurs formats de date en Java est un défi courant lors de la manipulation des dates. Les développeurs sont souvent confrontés à des problèmes lorsqu’ils doivent convertir des chaînes de caractères en dates, ou vice versa, en raison de la diversité des formats de date.

Solution

Heureusement, Java offre des fonctionnalités avancées pour gérer les dates, notamment la classe LocalDate qui permet de représenter une date sans tenir compte du fuseau horaire et de l’heure. Java 8 a également introduit une API Date/Time qui offre des fonctionnalités supplémentaires pour la manipulation des dates et heures, y compris la gestion de plusieurs formats de date différents.

Les développeurs peuvent utiliser des outils tels que DateTimeFormatter et DateTimeFormatterBuilder pour analyser et formater les dates dans différents formats. Ces outils permettent également de définir des modèles de formatage personnalisés et de gérer les erreurs liées à la conversion de dates.

Voici un exemple concret d’utilisation du DateTimeFormatter et du DateTimeFormatterBuilder pour gérer plusieurs formats de date :

package org.example;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Locale;

public class DateParser {

    private static final String[] SUPPORTED_FORMATS = {
            "dd/MM/yyyy",
            "dd-MM-yyyy",
            "yyyy/MM/dd",
            "yyyy-MM-dd"
    };

    public static LocalDate parseDate(String dateString) throws DateTimeParseException {
        DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
        Arrays.stream(SUPPORTED_FORMATS).forEach(f ->
                builder.appendOptional(DateTimeFormatter.ofPattern(f))
        );

        DateTimeFormatter formatter = builder.toFormatter(Locale.ENGLISH);
        return LocalDate.parse(dateString, formatter);
    }
}

Et voici comment formater une date dans un format spécifique :

public static String formatDate(LocalDate date, String pattern) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
    return date.format(formatter);
}

Enfin, voici comment combiner ces deux méthodes pour convertir une date d’un format à un autre :

public static String formatDate(String dateString, String pattern) throws DateTimeParseException {
    LocalDate date = null;
    for (String format : SUPPORTED_FORMATS) {
        try {
            date = LocalDate.parse(dateString, DateTimeFormatter.ofPattern(format));
            break;
        } catch (DateTimeParseException e) {
            // Le format ne correspond pas, on essaye avec le suivant
        }
    }
    if (date == null) {
        throw new DateTimeParseException("Aucun format supporté pour la date fournie", dateString, -1);
    }

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
    return date.format(formatter);
}

Discussion

Ces exemples montrent comment Java peut être utilisé pour gérer efficacement plusieurs formats de date. En comprenant ces concepts et en utilisant les outils appropriés, les développeurs peuvent éviter les erreurs courantes liées à la manipulation des dates en Java.

Pour s’assurer que notre code fonctionne comme prévu, il est important d’écrire des tests unitaires. Voici quelques tests que vous pouvez utiliser pour tester le code ci-dessus :

package org.example;

import static org.junit.jupiter.api.Assertions.*;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.Collection;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

public class DateParserTest {

    private DateParser dateParser;

    @BeforeEach
    void setUp() {
        dateParser = new DateParser();
    }

    @ParameterizedTest(name = "{index} - Parsing {0} should return {1}")
    @MethodSource("dateStrings")
    void testParseDate(String dateString, LocalDate expectedDate) {
        assertEquals(expectedDate, dateParser.parseDate(dateString));
    }

    @ParameterizedTest(name = "{index} - Parsing invalid date string {0} should throw DateTimeParseException")
    @MethodSource("invalidDateStrings")
    void testParseDateThrowsDateTimeParseException(String dateString) {
        assertThrows(DateTimeParseException.class, () -> dateParser.parseDate(dateString));
    }

    static Collection<Object[]> dateStrings() {
        return Arrays.asList(new Object[][] {
                { "10/03/2022", LocalDate.of(2022, 3, 10) },
                { "10-03-2022", LocalDate.of(2022, 3, 10) },
                { "2022/03/10", LocalDate.of(2022, 3, 10) },
                { "2022-03-10", LocalDate.of(2022, 3, 10) },
                { "31/12/2023", LocalDate.of(2023, 12, 31) },
                { "31-12-2023", LocalDate.of(2023, 12, 31) },
                { "2023/12/31", LocalDate.of(2023, 12, 31) },
                { "2023-12-31", LocalDate.of(2023, 12, 31) }
        });
    }

    static Collection<String> invalidDateStrings() {
        return Arrays.asList(new String[] {
                "10/13/2022", // invalid month
                "02/29/2021", // not a leap year
                "2022/31/10", // invalid day
                "10-03-22", // 2-digit year
                "invalid", // not a date string
                "2022/03/10 10:00:00" // not a date string
        });
    }

}

Ces tests vérifient que la méthode parseDate peut analyser correctement une date dans différents formats et qu’elle lance une exception DateTimeParseException lorsqu’elle reçoit une chaîne de caractères qui ne correspond à aucun format de date supporté. Ces tests aident à s’assurer que notre code est robuste et qu’il se comporte comme prévu dans différentes situations. Ils sont un élément essentiel pour garantir la qualité du code et éviter les erreurs inattendues. En utilisant ces tests comme guide, les développeurs peuvent être plus confiants dans la robustesse de leur code et dans sa capacité à gérer correctement plusieurs formats de date.

mardi 7 mars 2023

[Spring Boot] Comment éviter de retourner la stack trace au client dans une application Spring?

 Lorsque vous développez une application Spring Boot, il est important de gérer correctement les erreurs et les exceptions pour éviter de renvoyer des informations sensibles à un client.

Voici quelques conseils et exemples de bonnes pratiques pour éviter de retourner la stack trace au client : A partir de java 8 et avec l'introduction des optionnelles je préfére les utiliser pour gérer les exceptions proporements Voiçi un exemple de code

java
@RequestMapping("/api/users/{id}")
public User getUserById(@PathVariable Long id) {
 log.info("Fetching user with id: {}", id);
User user = userRepository.findById(id) 
 .orElseThrow(() -> {
     log.error("User with id {} not found", id);
    return new UserNotFoundException("User not found with id: " + id);
 });
return user;
}

Sinon je vous laisse lire les autres manières de faire :

  1. Ne renvoyez jamais la stack trace directement au client

Mauvaise pratique :

java
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
    return userService.getUserById(id);
}

Dans cet exemple, si une exception se produit lors de la recherche d'un utilisateur, la stack trace sera retournée au client.

Bonne pratique :

Dans l'exemple de mauvaise pratique, le renvoi de l'objet User directement peut renvoyer la stack trace au client en cas d'erreur, ce qui est peu convivial. En revanche, dans la bonne pratique, en renvoyant des réponses HTTP appropriées, vous offrez au client une réponse claire et structurée, améliorant ainsi l'expérience utilisateur.

java
@GetMapping("/users/{id}")
public
ResponseEntity<User> getUser(@PathVariable Long id) {
try {
    User user = userService.getUserById(id);
    return
ResponseEntity.ok(user);
 }
catch (UserNotFoundException e) {
    return
ResponseEntity.notFound().build();
 }
}

Dans cet exemple, nous retournons une réponse HTTP personnalisée en utilisant ResponseEntity. Si l'utilisateur n'est pas trouvé, nous retournons un code de statut 404 Not Found, plutôt que de renvoyer la stack trace au client.

  1. Loguez l'erreur pour faciliter le debugging

Mauvaise pratique :

java
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
    return userService.getUserById(id);
}

Dans cet exemple, si une exception se produit lors de la recherche d'un utilisateur, aucune information sur l'erreur n'est enregistrée.

Bonne pratique :

La journalisation des erreurs est essentielle pour le débogage.

Dans l'exemple de mauvaise pratique, aucune information sur l'erreur n'est enregistrée, ce qui complique le processus de débogage. En revanche, la bonne pratique enregistre les erreurs dans les fichiers journaux, ce qui facilite l'identification et la résolution des problèmes.

java
@GetMapping("/users/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
try {
User user = userService.getUserById(id);
return ResponseEntity.ok(user);
 }
catch (UserNotFoundException e) {
 
logger.error("L'utilisateur avec l'ID {} n'a pas été trouvé", id);
return ResponseEntity.notFound().build();
 }
catch (Exception e) {
 logger.error("Une erreur s'est produite lors de la recherche de l'utilisateur avec l'ID {}", id, e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
 }
}

Dans cet exemple, nous utilisons un logger pour enregistrer

3. Évitez d'utiliser les exceptions globales dans votre code. Cela peut renvoyer une stack trace complète au client, ce qui peut être exploité pour des attaques. Au lieu de cela, vous pouvez utiliser les exceptions personnalisées pour gérer les erreurs et renvoyer des messages d'erreur clairs aux clients.

Mauvaise pratique :

java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public ResponseEntity<Object> handleException(Exception exception) {
return new ResponseEntity<>("Erreur interne du serveur", HttpStatus.INTERNAL_SERVER_ERROR);
 }
}

Bonne pratique :

Les exceptions personnalisées permettent de renvoyer des messages d'erreur clairs et explicites aux clients sans divulguer la stack trace complète. Dans l'exemple de bonne pratique, en utilisant @ExceptionHandler pour gérer l'exception personnalisée MyCustomException, vous assurez que le client reçoit un message d'erreur compréhensible, améliorant ainsi la convivialité de l'API.

java
@ExceptionHandler(MyCustomException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public String handleMyException(MyCustomException ex) {
return ex.getMessage();
}
  1. Utilisez les fichiers de propriétés de configuration pour masquer les messages d'erreur dans la sortie JSON. Vous pouvez utiliser le fichier application.properties pour activer la configuration suivante :

Mauvaise pratique :


spring.jackson.serialization.fail-on-empty-beans=false
Pourquoi c'est une mauvaise pratique ?
Si vous avez des objets vides qui sont sérialisés en JSON et que vous les renvoyez au client, assurez-vous que cela ne compromet pas la sécurité. Parfois, un objet vide peut contenir des informations sensibles, et le fait de renvoyer un JSON vide peut exposer ces informations.

Bonne pratique :

La configuration des propriétés Jackson pour masquer les erreurs dans la sortie JSON est essentielle pour la sécurité. En configurant ces propriétés correctement, vous empêchez les informations sensibles, y compris la stack trace, d'être renvoyées au client. Cela réduit le risque d'exposition d'informations confidentielles.


spring.jackson.default-property-inclusion=NON_NULL spring.jackson.serialization.fail-on-empty-beans=true spring.jackson.deserialization.fail-on-unknown-properties=true

en résumé voici un tableau comparatif des annotations et classes que vous pouvez utiliser pour gérer les exceptions dans votre application :

Annotation/ClasseAvantagesInconvénients
@ExceptionHandlerPermet de définir une méthode de gestion des exceptions pour un contrôleur spécifique.La méthode doit être appelée explicitement à partir du contrôleur pour être exécutée.
@ResponseStatusPermet de définir un code de réponse HTTP personnalisé pour une exception.Ne fournit pas de mécanisme de traitement de l'exception en soi.
@ControllerAdvicePermet de définir une classe qui fournit des méthodes de gestion des exceptions pour tous les contrôleurs de l'application.Peut être moins efficace que la gestion des exceptions au niveau du contrôleur en termes de performances, car toutes les méthodes de gestion des exceptions de la classe seront appelées pour chaque exception levée dans l'application.
ResponseStatusException.classPermet de créer une exception personnalisée qui renvoie un code de réponse HTTP spécifique au client.Ne fournit pas de mécanisme de traitement de l'exception en soi.

La configuration de ces propriétés dans votre fichier de configuration de l'application Spring Boot peut influencer la façon dont les erreurs sont gérées et renvoyées au client.

  • server.error.include-binding-errors: cette propriété contrôle l'inclusion des erreurs de liaison dans la réponse d'erreur envoyée au client. Si elle est définie sur "never", les erreurs de liaison ne seront pas incluses dans la réponse d'erreur.

  • server.error.include-exception: cette propriété contrôle l'inclusion de l'exception dans la réponse d'erreur envoyée au client. Si elle est définie sur "false", l'exception ne sera pas incluse dans la réponse d'erreur.

  • server.error.include-message: cette propriété contrôle l'inclusion du message d'erreur dans la réponse d'erreur envoyée au client. Si elle est définie sur "never", le message d'erreur ne sera pas inclus dans la réponse d'erreur.

  • server.error.include-stacktrace: cette propriété contrôle l'inclusion de la stack trace dans la réponse d'erreur envoyée au client. Si elle est définie sur "never", la stack trace ne sera pas incluse dans la réponse d'erreur.

Si ces propriétés sont correctement configurées, les erreurs ne devraient pas être renvoyées avec la stack trace au client, ce qui peut améliorer la sécurité