I. Principe de fonctionnement de base du Filter

  • 1. Un programme Filter est une classe Java qui implémente une interface spéciale. Semblable à un Servlet, il est également invoqué et exécuté par le conteneur de Servlet.
  • 2. Lorsqu’un Filter est enregistré dans web.xml pour intercepter un programme Servlet, il peut décider s’il faut continuer à transmettre la requête au programme Servlet, et s’il faut modifier les messages de requête et de réponse.
  • 3. Lorsque le conteneur de Servlet commence à invoquer un programme Servlet, s’il constate qu’un programme Filter a été enregistré pour intercepter ce Servlet, le conteneur n’appelle plus directement la méthode service du Servlet. À la place, il appelle la méthode doFilter du Filter, qui décide alors s’il faut activer la méthode service.
  • 4. Toutefois, dans la méthode Filter.doFilter, vous ne pouvez pas appeler directement la méthode service du Servlet. À la place, vous appelez la méthode FilterChain.doFilter pour activer la méthode service du Servlet cible. L’objet FilterChain est transmis via les paramètres de la méthode Filter.doFilter.
  • 5. Tant que vous ajoutez du code de programme avant et après l’instruction qui appelle FilterChain.doFilter dans la méthode Filter.doFilter, vous pouvez implémenter certaines fonctions spéciales avant et après la réponse du Servlet.
  • 6. Si la méthode FilterChain.doFilter n'est pas appelée dans la méthode Filter.doFilter, la méthode service du Servlet cible ne sera pas exécutée. Ainsi, le Filter peut bloquer certaines requêtes d'accès illégales.

II. Chaîne de filtres

  • 1. Plusieurs programmes Filter peuvent être enregistrés dans une application Web, et chaque programme Filter peut intercepter un ou un groupe de programmes Servlet. Si plusieurs programmes Filter peuvent intercepter le processus d'accès d'un certain programme Servlet, lorsqu'une requête d'accès pour ce Servlet arrive, le conteneur Web combinera ces plusieurs programmes Filter en une chaîne de filtres (également appelée chaîne de filtres).
  • 2. L'ordre d'interception des Filters dans la chaîne de filtres est le même que leur ordre de mappage dans le fichier web.xml. L'appel de la méthode FilterChain.doFilter dans la méthode doFilter du Filter précédent activera la méthode doFilter du Filter suivant, et la méthode FilterChain.doFilter appelée dans la méthode doFilter du dernier Filter activera la méthode service du Servlet cible.
  • 3. Tant qu'un Filter de la chaîne de filtres n'appelle pas la méthode FilterChain.doFilter, la méthode service du Servlet cible ne sera pas exécutée.

III. Interface Filter

Un programme Filter est une classe Java, et cette classe doit implémenter l'interface Filter. L'interface javax.servlet.Filter définit trois méthodes : init, doFilter et destroy.

1. Méthode init

  • (1) Lorsque l'application Web démarre, le serveur Web (conteneur Web) créera un objet instance pour chaque Filter enregistré en fonction des informations de configuration de son fichier web.xml, et le stockera en mémoire.
  • (2) Après que le conteneur Web a créé l'objet instance du Filter, il appellera immédiatement la méthode init de cet objet Filter. La méthode init n'est exécutée qu'une seule fois dans le cycle de vie du Filter. Lorsque le conteneur Web appelle la méthode init, il transmet un objet FilterConfig qui contient les informations de configuration et d'environnement d'exécution du Filter.

    public voic init(FilterConfig filterConfig) throws ServletException
  • (3) Les développeurs peuvent exécuter des fonctions d'initialisation similaires aux constructeurs dans la méthode init. Notez que si le code d'initialisation doit utiliser l'objet FilterConfig, ce code ne peut être écrit que dans la méthode init, et non dans le constructeur (étant donné que la méthode init n'a pas encore été appelée, l'objet FilterConfig n'a pas encore été créé, et son utilisation provoquerait certainement une erreur).

2. Méthode doFilter

Lorsqu'un objet Filter est capable d'intercepter des requêtes d'accès, le conteneur de servlets appellera la méthode doFilter de l'objet Filter.

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException.ServletException

Parmi ceux-ci, les paramètres request et response sont les objets de requête et de réponse transmis par le conteneur Web ou le Filter précédent dans la chaîne de filtres ; le paramètre chain est l'objet représentant la chaîne de filtres actuelle.

3. Méthode destroy

Cette méthode est appelée avant que le conteneur Web ne décharge l'objet Filter, et elle n'est également exécutée qu'une seule fois. Elle peut remplir la fonction opposée de la méthode init, en libérant les ressources ouvertes par l'objet Filter, telles que la fermeture des connexions à la base de données et des flux d'E/S.


IV. Interface FilterChain

Cette interface est utilisée pour définir les méthodes qu'un objet de chaîne de filtres doit fournir à l'extérieur. Cette interface ne définit qu'une seule méthode doFilter.

public void doFilter(ServletRequest request, ServletResponse response) throws java.io.IOException.ServletException

La méthode doFilter de l'interface FilterChain est utilisée pour indiquer au conteneur Web de transmettre la requête au filtre suivant dans la chaîne de filtres pour traitement. Si l'objet Filter actuel qui appelle cette méthode est le dernier Filter de la chaîne de filtres, la requête sera remise au programme Servlet cible pour traitement.


V. Interface FilterConfig

  • 1. Comme les programmes Servlet ordinaires, les programmes Filter peuvent également avoir besoin d'accéder au conteneur de servlets. La spécification Servlet encapsule l'objet ServletContext et les informations de paramètres de configuration du Filter dans un objet appelé FilterConfig.
  • 2. L'interface FilterConfig est utilisée pour définir les méthodes qu'un objet FilterConfig doit fournir à l'extérieur, afin que, dans un programme Filter, ces méthodes puissent être appelées pour obtenir l'objet ServletContext, ainsi que le nom convivial et les paramètres d'initialisation définis pour le Filter dans le fichier web.xml.
  • 3. Méthodes définies par l'interface FilterConfig :

    • méthode getFilterName : renvoie la valeur définie dans l'élément <filter-name>.

    • méthode getServletContext : renvoie une référence à l'objet ServletContext encapsulé dans l'objet FilterConfig.

    • méthode getInitParameter : utilisée pour renvoyer la valeur d'un paramètre d'initialisation avec un nom spécifié défini pour le Filter dans le fichier web.xml.

    • méthode getInitParameterNames : renvoie un objet de collection Enumeration.


VI. Enregistrement et mappage d'un Filter

1. Enregistrement d'un Filter

Un élément <filter> est utilisé pour enregistrer un Filter. Parmi ceux-ci, l'élément <filter-name> est obligatoire, l'élément <filter-class> est également obligatoire, et l'élément <init-param> est facultatif ; il peut y avoir plusieurs éléments <init-param>.

<filter>
    <filter-name>FirstFilter</filter-name>
    <filter-class>FirstFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>GB2312</param-value>
    </init-param>
</filter>

2. Mappage d'un Filter

L'élément <filter-mapping> est utilisé pour définir les ressources qu'un Filter est chargé d'intercepter. Les ressources interceptées par un Filter peuvent être spécifiées de deux manières : le chemin de requête d'accès à la ressource et le nom du Servlet.

Première méthode : spécifier le chemin d'accès à la ressource

<filter-mapping>
    <filter-name>FirstFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

Le paramétrage du chemin d'accès dans l'élément <url-pattern> suit la spécification de mappage d'URL de Servlet.

  • /*Indique que toutes les requêtes d'accès sont interceptées.
  • /filter/*Indique l'interception de toutes les requêtes d'accès sous le répertoire filter, telles que : http://localhost:8888/testFilter_001/filter/xxxxxx.
  • /test.htmlIndique l'interception des requêtes d'accès ayant test.html comme nom de ressource dans le répertoire racine ; le lien d'accès sera uniquement : http://localhost:8888/test.html.

Deuxième méthode : spécifier le nom du Servlet

<filter-mapping>
    <filter-name>FirstFilter</filter-name>
    <servlet-name>default></servlet-name>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>

(1) L'élément <servlet-name> et l'élément <url-pattern> sont mutuellement exclusifs ; leur valeur est le nom enregistré d'un Servlet dans le fichier web.xml.

(2) L'élément <dispatcher> a quatre valeurs possibles : REQUEST, INCLUDE, FORWARD, ERROR, correspondant respectivement aux quatre manières dont le conteneur de Servlet invoque des ressources :

  • Appelé via des requêtes d'accès normales ;

  • Appelé via la méthode RequestDispatcher.include ;

  • Appelé via la méthode RequestDispatcher.forward ;

  • Appelé en tant que ressource de réponse d'erreur.

Si l'élément enfant <dispatcher> n'est pas défini, cela équivaut au cas REQUEST. Plusieurs éléments enfants <dispatcher> peuvent également être définis pour spécifier que le Filter intercepte plusieurs méthodes d'invocation de la ressource.


VII. Exemple de programme de filtre

FitstFilter.java

import java.io.IOException; import java.io.PrintWriter; import java.util.Enumeration; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class FirstFilter implements Filter { private FilterConfig filterConfig = null; String paramValue = null; @Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; paramValue = filterConfig.getInitParameter("encoding"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("début des en-têtes-------------------"); Enumeration<?> headerNames = ((HttpServletRequest)request).getHeaderNames(); while(headerNames.hasMoreElements()) { String headerName = (String)headerNames.nextElement(); System.out.println(headerName + ": " + ((HttpServletRequest)request).getHeader(headerName)); } System.out.println("fin des en-têtes-------------------"); //Écrire le contenu de la réponse avant d'invoquer la cible response.setContentType("text/html; charset=gb2312"); PrintWriter out = response.getWriter(); out.println("L'adresse IP est :" + request.getRemoteHost() + "<br>"); chain.doFilter(request, response); //Écrire le contenu de la réponse après le retour de la cible out.println("<br>La valeur du paramètre d'initialisation nommé encoding est :" + paramValue); out.println("<br>Le chemin réel de l'application Web actuelle est :" + filterConfig.getServletContext().getRealPath("/")); //out.println("<br>le fichier test.html a été modifié !"); } @Override public void destroy() { this.filterConfig = null; } }

web.xml

<filter> <filter-name>FirstFilter</filter-name> <filter-class>FirstFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>GB2312</param-value> </init-param> </filter> <filter-mapping> <filter-name>FirstFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

test.html (situé dans le répertoire filter sous le chemin WebContent)

<html> <head> <meta charset="UTF-8"> <title>Insérer le titre ici</title> </head> <body>Ceci est le contenu original de la page test.html !</body> </html>

Accès :http://localhost:8888/testFilter_001/filter/test.html

Source de l'article : https://my.oschina.net/u/1171518/blog/265467