제이온

[Spring] Filter, Interceptor, Argument Resolver, qu'est-ce que c'est ?

Création: 2024-04-27

Création: 2024-04-27 00:41

Qu'est-ce qu'un filtre (Filter) ?

Un filtre est une fonctionnalité standard J2EE qui permet de traiter des tâches supplémentaires pour toutes les requêtes correspondant à un motif d'URL, avant ou après que la requête ne soit transmise au servlet de répartition (Dispatcher Servlet). En d'autres termes, il est géré par le conteneur Web (comme Tomcat) plutôt que par le conteneur Spring, ce qui signifie qu'il traite les requêtes avant qu'elles n'atteignent le servlet de répartition.


[Spring] Filter, Interceptor, Argument Resolver, qu'est-ce que c'est ?


Implémentation d'un filtre (Filter)

Pour ajouter un filtre, il faut implémenter l'interface Filter de javax.servlet, qui possède les trois méthodes suivantes :


  • Méthode init
    • Cette méthode permet d'initialiser l'objet filtre et de l'ajouter au service. Le conteneur Web appelle la méthode init une seule fois pour initialiser l'objet filtre. Ensuite, les requêtes suivantes sont traitées via la méthode doFilter().
  • Méthode doFilter
    • Cette méthode est exécutée par le conteneur Web pour chaque requête HTTP correspondant au motif d'URL avant qu'elle ne soit transmise au servlet de répartition, et avant que le servlet de répartition n'envoie la réponse HTTP au client.
      La méthode doFilter() prend en paramètre FilterChain, qui permet de transmettre la requête à la destination suivante via doFilter(). En insérant le processus de traitement nécessaire avant et après chain.doFilter(), nous pouvons exécuter le traitement souhaité.
  • Méthode destroy
    • Cette méthode permet de supprimer l'objet filtre du service et de renvoyer les ressources utilisées. Elle est appelée une seule fois par le conteneur Web, et l'objet filtre n'est plus traité par doFilter() par la suite.


Exemple de code - Spécification Servlet


Exemple de code - @Component


  • @Component : permet d'enregistrer le filtre en tant que bean Spring.
  • @Order : permet de définir l'ordre des filtres s'il y en a plusieurs.
  • Si un filtre est enregistré en tant que bean Spring de cette manière, il peut utiliser d'autres beans Spring.


Exemple de code - @Configuration

Si vous souhaitez que le filtre ne s'exécute que pour certaines URI, vous pouvez utiliser FilterRegistrationBean pour enregistrer le filtre en tant que bean Spring.


Utilisations d'un filtre (Filter)

Il est principalement utilisé pour valider et traiter les paramètres de la requête elle-même.


  • Tâches communes liées à la sécurité
    • Étant donné que les filtres fonctionnent au niveau du conteneur Web, ils peuvent effectuer des vérifications de sécurité (comme la protection contre les attaques XSS et CSRF) et bloquer les requêtes invalides. Cela empêche les requêtes d'atteindre le conteneur Spring, ce qui renforce encore la sécurité.
  • Journalisation de toutes les requêtes
  • Compression d'images/données et encodage de chaînes de caractères
    • Les filtres implémentent des fonctionnalités couramment utilisées dans les applications Web, comme la compression d'images ou de données et l'encodage de chaînes de caractères.
  • Personnalisation de ServletRequest
    • HttpServletRequest ne peut lire le contenu du corps qu'une seule fois. Par conséquent, Filter ou Interceptor ne peut pas lire le corps. Nous pouvons créer un ServletRequest personnalisé pour journaliser le corps.


Intercepteur (Interceptor)

Qu'est-ce qu'un intercepteur (Interceptor) ?

Contrairement aux filtres (Filter), qui sont une spécification J2EE standard, les intercepteurs (Interceptor) sont une fonctionnalité fournie par Spring. Ils permettent de référencer ou de modifier les requêtes et les réponses avant et après que le servlet de répartition n'appelle le contrôleur. En d'autres termes, contrairement aux filtres, qui fonctionnent au niveau du conteneur Web, les intercepteurs fonctionnent au niveau du contexte Spring.


Le servlet de répartition effectue une requête de mappage de gestionnaire pour trouver le contrôleur approprié, et renvoie une chaîne d'exécution (HandlerExecutionChain) en conséquence. Si cette chaîne d'exécution contient un ou plusieurs intercepteurs enregistrés, ils sont exécutés séquentiellement avant l'exécution du contrôleur. S'il n'y a pas d'intercepteur, le contrôleur est exécuté directement.


Implémentation d'un intercepteur (Interceptor)

Pour ajouter un intercepteur, il faut implémenter l'interface HandlerInterceptor de org.springframework.web.servlet, qui possède les trois méthodes suivantes :


  • Méthode preHandle
    • La méthode preHandle est exécutée avant l'appel du contrôleur. Elle peut donc être utilisée pour effectuer des tâches de prétraitement, modifier les informations de la requête ou ajouter des informations avant l'appel du contrôleur.
    • Le troisième paramètre de la méthode preHandle, handler, est un objet qui encapsule les informations de la méthode annotée @RequestMapping.
    • Le type de retour de la méthode preHandle est un booléen. Si la valeur de retour est true, l'exécution se poursuit à l'étape suivante. Si elle est false, l'exécution s'arrête et les étapes suivantes (l'intercepteur suivant ou le contrôleur) ne sont pas exécutées.
  • Méthode postHandle
    • La méthode postHandle est exécutée après l'appel du contrôleur. Elle peut donc être utilisée pour effectuer des tâches de post-traitement après l'appel du contrôleur.
  • Méthode afterCompletion
    • Comme son nom l'indique, la méthode afterCompletion est exécutée une fois que toutes les opérations sont terminées, y compris la génération du résultat final par toutes les vues.


Exemple de code


  • Enregistrez l'intercepteur créé en tant que bean.
  • Enregistrez l'intercepteur créé dans la méthode addInterceptors() de l'interface WebMvcConfigurer.
  • Les intercepteurs sont exécutés dans l'ordre dans lequel ils sont enregistrés dans InterceptorRegistry.


Utilisations d'un intercepteur (Interceptor)

Il est principalement utilisé pour traiter la cohérence des informations de requête à l'aide de la logique métier.


  • Tâches communes comme l'authentification et l'autorisation
    • Par exemple, vous pouvez vérifier l'authentification ou l'autorisation avant de transmettre la requête au contrôleur.
  • Journalisation des appels d'API
    • Vous pouvez enregistrer des informations sur le client via les objets HttpServletRequest et HttpServletResponse transmis.
  • Traitement des données transmises au contrôleur
    • Vous pouvez traiter les objets HttpServletRequest et HttpServletResponse transmis et les transmettre au contrôleur.
  • Simulation d'AOP
    • Le troisième paramètre de la méthode preHandle(), HandlerMethod, fournit des informations supplémentaires sur la méthode à exécuter, telles que la signature de la méthode, qui peuvent être utilisées pour déterminer si la logique doit être exécutée ou non.


Filtre (Filter) vs Intercepteur (Interceptor)

  • Les filtres s'exécutent dans le contexte Web, tandis que les intercepteurs s'exécutent dans le contexte Spring. Par conséquent, le moment de l'exécution est différent.
  • Les filtres peuvent gérer les opérations avant et après le servlet de répartition, tandis que les intercepteurs peuvent gérer les opérations avant et après le contrôleur.
  • Les filtres sont mieux adaptés aux tâches qui doivent être traitées globalement indépendamment de Spring, à la validation des paramètres d'entrée eux-mêmes ou à l'utilisation de ServletRequest au lieu de HttpServletRequest.
  • Les intercepteurs sont mieux adaptés aux tâches qui doivent être traitées globalement pour les requêtes entrantes au niveau Spring, ou lorsqu'il est nécessaire d'inclure une logique métier.
  • Les intercepteurs peuvent utiliser @ControllerAdvice et @ExceptionHandler pour gérer les exceptions, tandis que les filtres ne le peuvent pas.
    • Les filtres gèrent généralement les exceptions qui se produisent au moment de l'exécution en enveloppant la méthode doFilter() dans un bloc try-catch.


Argument Resolver

Qu'est-ce qu'un Argument Resolver ?

Un Argument Resolver peut indirectement créer l'objet souhaité à partir de la valeur de la requête lorsqu'une requête est envoyée au contrôleur.


Utilisations d'un Argument Resolver

Par exemple, supposons qu'une requête arrive avec un jeton JWT. Nous devons valider si ce jeton est valide, puis extraire l'ID stocké dans le jeton et le convertir en un objet utilisateur connecté.

Sans Argument Resolver, nous devrions implémenter le processus de validation du jeton et de conversion en objet utilisateur connecté dans chaque contrôleur. Cela entraînerait une duplication de code dans les contrôleurs nécessitant une validation utilisateur et augmenterait la responsabilité des contrôleurs. Argument Resolver peut résoudre ce problème.


Implémentation d'un Argument Resolver

Un Argument Resolver peut être utilisé en implémentant HandlerMethodArgumentResolver. Cette interface spécifie que les deux méthodes suivantes doivent être implémentées.



  • Méthode supportsParameter
    • Une annotation spécifique est ajoutée au paramètre pour lequel vous souhaitez que l'Argument Resolver s'exécute. La méthode supportsParameter() vérifie si l'annotation souhaitée est présente dans l'argument de la méthode demandée et renvoie true si elle l'est.
  • Méthode resolveArgument
    • Si supportsParameter renvoie true, c'est-à-dire s'il existe une méthode avec une annotation spécifique, cette méthode lie le paramètre au format souhaité et le renvoie.


Si nous utilisons Argument Resolver, l'implémentation du contrôleur est la suivante :



Différences entre Argument Resolver et Intercepteur (Interceptor)

  • ArgumentResolver fonctionne après l'intercepteur et renvoie l'objet souhaité à partir de la valeur de la requête lorsqu'une requête est envoyée au contrôleur.
  • En revanche, l'intercepteur intercepte la requête avant l'exécution du contrôleur et ne peut pas renvoyer d'objet spécifique. Il n'a que des types de retour boolean ou void.


Sources


Questions d'entretien prévues et réponses

Qu'est-ce qu'un filtre ?

Un filtre permet de traiter des tâches supplémentaires pour toutes les requêtes correspondant à un motif d'URL, avant ou après que la requête ne soit transmise au servlet de répartition, et fonctionne au niveau du conteneur de servlet.


Quand utiliser un filtre ?

Les filtres peuvent être utilisés pour traiter des tâches qui doivent être traitées globalement indépendamment de Spring. Ou, ils sont utilisés pour valider les paramètres de la requête.

Plus précisément, ils sont utilisés pour traiter les tâches communes liées à la sécurité, la journalisation de toutes les requêtes, la compression d'images/données et l'encodage de chaînes de caractères, et la personnalisation de ServletRequest.


Qu'est-ce qu'un intercepteur ?

Un intercepteur permet de référencer ou de modifier les requêtes et les réponses avant et après que le servlet de répartition n'appelle le contrôleur, et fonctionne au niveau du conteneur Spring.


Quand utiliser un intercepteur ?

Les intercepteurs peuvent être utilisés pour traiter des tâches qui doivent être traitées globalement pour les requêtes entrantes. Ils sont principalement utilisés lorsque la logique métier doit être appelée lors de la validation.

Plus précisément, ils sont utilisés pour traiter les tâches communes comme l'authentification/autorisation, la journalisation des appels d'API et le traitement des données transmises au contrôleur.


Quelle est la différence entre un filtre et un intercepteur ?

Les filtres s'exécutent au niveau du conteneur de servlet, tandis que les intercepteurs s'exécutent au niveau du conteneur Spring.

Les filtres peuvent gérer les opérations avant et après le servlet de répartition, tandis que les intercepteurs peuvent gérer les opérations avant et après le contrôleur.

Par conséquent, il est préférable d'utiliser des filtres pour les tâches qui doivent être traitées globalement indépendamment de Spring, et des intercepteurs pour les tâches qui doivent être traitées globalement pour les requêtes entrantes au niveau Spring.


Qu'est-ce qu'un Argument Resolver ?

Un Argument Resolver permet de créer indirectement l'objet souhaité à partir de la valeur de la requête lorsqu'une requête est envoyée au contrôleur.


Quand utiliser un Argument Resolver ?

Il peut être utilisé lorsque la requête est reçue avec un jeton JWT et qu'il faut valider si le jeton est valide, puis extraire l'ID stocké dans le jeton et le convertir en un objet LoginMember.


Quelle est la différence entre un intercepteur et un Argument Resolver ?

Un Argument Resolver renvoie l'objet souhaité à partir de la valeur de la requête lorsqu'une requête est envoyée au contrôleur. En revanche, un intercepteur ne peut pas renvoyer d'objet de cette manière, et Argument Resolver est exécuté après l'exécution de l'intercepteur.

Commentaires0

[Hors informatique, survivre en tant que développeur] 14. Résumé des questions techniques fréquemment posées lors d'un entretien d'embauche pour développeur débutantNous avons résumé et organisé les questions techniques fréquemment posées lors des entretiens d'embauche pour les développeurs débutants (zones de mémoire, structures de données, bases de données, etc.). Nous espérons que cela vous aidera dans votre prépa
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자
투잡뛰는 개발 노동자

April 3, 2024