Skip Navigation Links
Accueil
Java Standard EditionExpand Java Standard Edition
Java EE 5Expand Java EE 5
Visual Basic .Net 2005Expand Visual Basic .Net 2005
Visual C++ .Net 2005Expand Visual C++ .Net 2005
Visual C# .Net 2005Expand Visual C# .Net 2005
Cours ASP .Net 2.0Expand Cours ASP .Net 2.0
PostgresqlExpand Postgresql
LinuxExpand Linux
Visual Studio 2008Expand Visual Studio 2008
ASP 3.0 ClassiqueExpand ASP 3.0 Classique
Cours Javascript - DOM - DHTMLExpand Cours Javascript - DOM - DHTML
Cours AjaxExpand Cours Ajax
VBAExpand VBA
AssembleurExpand Assembleur
PerlExpand Perl
MembresExpand Membres
L'auteur du site
Nouveautés sur le site
Contacts
Plan du site
Accueil > Java EE 5 > Les filtres Java (javax.servlet.Filter)
____________________________________________________________________________________________________
Connexion

LES FILTRES EN JAVA (javax.servlet.filter)

1/6/2008

Testé sur Tomcat 5.5.17

Au démarrage de Tomcat, un fichier texte « localhost.2008-06-01 », se trouvant dans C:\Program Files\Apache Software Foundation\Tomcat 5.5\logs, est créé.

Dans Tomcat 5.5.17, il existe une application servlets-examples. Dans le web.xml de cette application web (qui se trouve dans son dossier WEB-INF), il y a ceci :

Created with colorer-take5 library. Type 'xml'

<filter>
        <filter-name>Path Mapped Filter</filter-name>
        <filter-class>filters.ExampleFilter</filter-class>

    <init-param>
        <param-name>attribute</param-name>
        <param-value>filters.ExampleFilter.PATH_MAPPED</param-value>

    </init-param>
    </filter>

Et ceci un peu plus loin :
Created with colorer-take5 library. Type 'xml'

 <!-- Define filter mappings for the defined filters -->
(…)
<filter-mapping>
        <filter-name>Path Mapped Filter</filter-name>
    <url-pattern>/servlet/*</url-pattern>

    </filter-mapping>


On prendra cet exemple pour comprendre les filtres. D’autres filtres sont déclarés dans cet exemple, qui se déclenchent selon un certain contexte, mais nous n’en parlerons pas pour l’instant.

La balise <filter> est la déclaration du filtre nommé « Path Mapped Filter », et dont la classe est « filters .ExampleFilter ».

La classe ExampleFilter se trouve dans le répertoire WEB-INF/classes/filters de notre application. Cette classe fait partie d’un package appelé « filters ».

La balise <filter-mapping> effectue le mapping entre un filtre et un modèle d’url (par exemple, cela peut être aussi une servlet, le nom de la servlet est alors dans une balise maServlet. On rappelle qu’on définit une servlet dans le fichier web.xml, en faisant
<servlet>
<servlet-name>maServlet</servlet-name>
<servlet-class>monPackage.maClasse</servlet-class>
</servlet>

ce qui effectue une sorte de mapping entre un nom « logique » de servlet, et sa classe.

Dans le cas du mapping entre un filtre et un modèle d’url, ce qui est notre cas ici, on rajoute
une balise <url-pattern> :
<url-pattern>/servlet/*</url-pattern>

La racine ici est relative à l’application web courante, cela veut dire qu’ici, toutes les url du type http://127.0.0.1:8080/servlets-examples/servlet/* sont valides. Vous pouvez créer un dossier « servlet » dans votre dossier « servlets-example », et y mettre vos pages.

Chaque url de cette forme, entraînera l’exécution du filtre « Path Mapped Filter », qui est de la classe filters.ExampleFilter.
On note qu’il est possible de passer en paramètre au filtre des valeurs, avec la balise <init-param> :
Created with colorer-take5 library. Type 'xml'

 <init-param>
        <param-name>attribute</param-name>
        <param-value>filters.ExampleFilter.SERVLET_MAPPED</param-value>

    </init-param>

Ici, on donne à notre classe de filtre, un paramètre, appelé « attribute », et qui a pour valeur «filters.ExampleFilter.PATH_MAPPED» . Nous pourrons récupérer cette valeur, correspondant à la clé « attribute », dans notre classe de filtre (nous verrons comment).

Regardons maintenant le code de la classe ExampleFilter :

Created with colorer-take5 library. Type 'java'

/*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0

*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package filters;


import java.io.IOException;
import javax.servlet.Filter;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;


/**
* Example filter that can be attached to either an individual servlet
* or to a URL pattern. This filter performs the following functions:
* <ul>

* <li>Attaches itself as a request attribute, under the attribute name
* defined by the value of the <code>attribute</code> initialization

* parameter.</li>
* <li>Calculates the number of milliseconds required to perform the
* servlet processing required by this request, including any

* subsequently defined filters, and logs the result to the servlet
* context log for this application.
* </ul>
*

* @author Craig McClanahan
* @version $Revision: 267129 $ $Date: 2004-03-18 11:40:35 -0500 (Thu, 18 Mar 2004) $

*/

public final class ExampleFilter implements Filter {


// ----------------------------------------------------- Instance Variables


/**
* The request attribute name under which we store a reference to ourself.
*/
private String attribute = null;


/**
* The filter configuration object we are associated with. If this value
* is null, this filter instance is not currently configured.
*/

private FilterConfig filterConfig = null;


// --------------------------------------------------------- Public Methods


/**
* Take this filter out of service.

*/
public void destroy() {

this.attribute = null;

this.filterConfig = null;

}


/**
* Time the processing that is performed by all subsequent filters in the

* current filter stack, including the ultimately invoked servlet.
*
* @param request The servlet request we are processing
* @param result The servlet response we are creating

* @param chain The filter chain we are processing
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs

*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)

throws IOException, ServletException {

// Store ourselves as a request attribute (if requested)
if (attribute != null)

request.setAttribute(attribute, this);

// Time and log the subsequent processing
long startTime = System.currentTimeMillis();

chain.doFilter(request, response);
long stopTime = System.currentTimeMillis();

filterConfig.getServletContext().log
(this.toString() + ": " + (stopTime - startTime) +

" milliseconds");

}


/**
* Place this filter into service.
*

* @param filterConfig The filter configuration object
*/
public void init(FilterConfig filterConfig) throws ServletException {

this.filterConfig = filterConfig;
this.attribute = filterConfig.getInitParameter("attribute");

}


/**
* Return a String representation of this object.
*/
public String toString() {

if (filterConfig == null)
return ("InvokerFilter()");

StringBuffer sb = new StringBuffer("InvokerFilter(");
sb.append(filterConfig);

sb.append(")");
return (sb.toString());

}

}



Cette classe implémente l’interface javax.servlet.Filter , dont le code source est le suivant :

Created with colorer-take5 library. Type 'java'

/*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0

*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package javax.servlet;

import java.io.IOException;

    /** 
    * A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.

        * <br><br>
    * Filters perform filtering in the <code>doFilter</code> method. Every Filter has access to 
    ** a FilterConfig object from which it can obtain its initialization parameters, a

    ** reference to the ServletContext which it can use, for example, to load resources
    ** needed for filtering tasks.

    ** <p>
    ** Filters are configured in the deployment descriptor of a web application
    ** <p>

    ** Examples that have been identified for this design are<br>
    ** 1) Authentication Filters <br>
    ** 2) Logging and Auditing Filters <br>

    ** 3) Image conversion Filters <br>
        ** 4) Data compression Filters <br>
    ** 5) Encryption Filters <br>

    ** 6) Tokenizing Filters <br>
    ** 7) Filters that trigger resource access events <br>
    ** 8) XSL/T filters <br>

    ** 9) Mime-type chain Filter <br>
     * @since    Servlet 2.3

    */

public interface Filter {

    /** 
    * Called by the web container to indicate to a filter that it is being placed into

    * service. The servlet container calls the init method exactly once after instantiating the
    * filter. The init method must complete successfully before the filter is asked to do any
    * filtering work. <br><br>


         * The web container cannot place the filter into service if the init method either<br>
        * 1.Throws a ServletException <br>
        * 2.Does not return within a time period defined by the web container 

    */
    public void init(FilterConfig filterConfig) throws ServletException;

    
    
    /**
    * The <code>doFilter</code> method of the Filter is called by the container
    * each time a request/response pair is passed through the chain due

    * to a client request for a resource at the end of the chain. The FilterChain passed in to this
    * method allows the Filter to pass on the request and response to the next entity in the
    * chain.<p>
    * A typical implementation of this method would follow the following pattern:- <br>

    * 1. Examine the request<br>
    * 2. Optionally wrap the request object with a custom implementation to
    * filter content or headers for input filtering <br>

    * 3. Optionally wrap the response object with a custom implementation to
    * filter content or headers for output filtering <br>
    * 4. a) <strong>Either</strong> invoke the next entity in the chain using the FilterChain object (<code>chain.doFilter()</code>), <br>   

    ** 4. b) <strong>or</strong> not pass on the request/response pair to the next entity in the filter chain to block the request processing<br>
    ** 5. Directly set headers on the response after invocation of the next entity in the filter chain.

    **/
    public void doFilter ( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException, ServletException;

    /**
    * Called by the web container to indicate to a filter that it is being taken out of service. This 
    * method is only called once all threads within the filter's doFilter method have exited or after
    * a timeout period has passed. After the web container calls this method, it will not call the

    * doFilter method again on this instance of the filter. <br><br>
    * 
         * This method gives the filter an opportunity to clean up any resources that are being held (for
    * example, memory, file handles, threads) and make sure that any persistent state is synchronized

    * with the filter's current state in memory.
    */

    public void destroy();


}


Commençons l’explication de notre classe ExampleFilter :

Elle possède comme attribut un objet appelé « filterConfig », de l‘interface javax.servlet.FilterConfig. Le code source de cette interface nous informe qu’elle sert à construire un objet « A filter configuration object used by a servlet container
to pass information to a filter during initialization. ». Cela signifie que c’est un objet de configuration de filter, et qui est utilisé par le conteneur de servlet (Tomcat), pour passer l’information au filter lors de l’initialisation. C’est un objet d’interfaçage entre Tomcat et le filtre.

La méthode init, de l’interface Filter, possède un unique paramètre, de type FilterConfig. Le conteneur de servlet nous donne cet objet, lorsqu’il l’appelle. Code source de Filter : «
Called by the web container to indicate to a filter that it is being placed into service. The servlet container calls the init method exactly once after instantiating the filter. The init method must complete successfully before the filter is asked to do any filtering work. "
La méthode init est appelée une seule fois, et juste après que le filtre ait été instancié. Elle permet de procéder à des initialisations nécessaires pour le filtre. Dans l’exemple ici,

Created with colorer-take5 library. Type 'java'

public void init(FilterConfig filterConfig) throws ServletException {

    this.filterConfig = filterConfig;

        this.attribute = filterConfig.getInitParameter("attribute");

    }


La méthode init garde l’objet FilterConfig, dans son attribut filterConfig. Il lui sera utile éventuellement par la suite.
Puis elle initialise son attribut « this.attribute », avec la valeur de l’init-param « attribute » qu’on avait nous-même donné dans le web.xml, et qu’on réussi à récupérer grâce à l’objet FilterConfig ( avec la méthode getInitParameter de l’interface FilterConfig, qui prend le nom de la clé, une string, en paramètre, et qui retourne la valeur sous forme de string, ou null si la clé n’existe pas).

La méthode doFilter de l’interface Filter, est appelé lorsque le filtre doit être passé. Voyons celle de notre exemple :

Created with colorer-take5 library. Type 'java'

public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
    throws IOException, ServletException {

    // Store ourselves as a request attribute (if requested)
    if (attribute != null)

        request.setAttribute(attribute, this);

    // Time and log the subsequent processing
    long startTime = System.currentTimeMillis();

        chain.doFilter(request, response);
    long stopTime = System.currentTimeMillis();

    filterConfig.getServletContext().log
        (this.toString() + ": " + (stopTime - startTime) +

         " milliseconds");

    }


L’objet d’interfaçage filterConfig nous permet d’obtenir un objet implémentant l’interface javax.servlet.ServletContext. Cet objet ServletContext possède une méthode « log », dont le prototype est public void log(String msg);
Elle prend une string en paramètre, et, comme nous dit le code source de l’interface ServletContext : « Writes the specified message to a servlet log file, usually an event log. The name and type of the servlet log file is specific to the servlet container.”. Elle rajoute le message qu’on lui a passé au fichier journal des servlets, qui pour nous est “ C:\Program Files\Apache Software Foundation\Tomcat 5.5\logs\ localhost.2008-06-01.log" .

Lorsque le filtre ExampleFilter est demandé, pour nous lorsqu’une url de la forme http://127.0.0.1:8080/servlets-examples/servlet/* est tapée, la méthode doFilter du filtre est exécutée (bien sûr d’autres filtres peuvent s’exécuter éventuellement avant et après).

Notre méthode doFilter ajoute tout d’abord un attribut à l’objet request. Notre attribut à la valeur « filters.ExampleFilter.PATH_MAPPED », et on le met à this, qui est notre objet. Ainsi, quelqu’un qui veut savoir qui est le filtre « filters.ExampleFilter.PATH_MAPPED », peut l’obtenir à partir de l’objet request. L’objet request est du type javax.ServletRequest (qui est une interface). Cette interface possède une méthode dont la signature est :
“public void setAttribute( String name, Object o);”, et a aussi une méthode “public Object getAttribute( String name ) ; ».

L’interface javax.servlet.FilterChain est , d’après le code source :
« A FilterChain is an object provided by the servlet container to the developer giving a view into the invocation chain of a filtered request for a resource. Filters use the FilterChain to invoke the next filter in the chain, or if the calling filter is the last filter in the chain, to invoke the resource at the end of the chain. ».
Un objet FilterChain représente la chaine d’appel des différents filtres devant s’appliquer pour une ressource demandée (une url, une servlet…, ici une url). Cet objet nous est donné par le conteneur de servlet (Tomcat), c’est un paramètre de la méthode doPost de Filter. La méthode doPost du premier filtre est appelée par le conteneur de servlet. A l’intérieur de celle-ci, elle peut appeler ou pas les filtres suivant, par un appel à la méthode doFilter de l’objet FilterChain : « chain.doFilter( request, response) ; ». A partir de cet appel, le conteneur de servlets, comme le précise la javadoc de doFilter (http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/Filter.html) , va appeler la méthode doPost du filtre suivant, ou, s’il n’y a plus de filtre, va appeler la ressource. Un filtre peut par conséquent décider de ne pas appliquer les filtres suivants.

Ici on calcule la durée, en millisecondes, de l’appel à la ressource (et des filtres suivants), grâce à la méthode System.currentTimeMillis( ) .

La méthode Destroy ( public Destroy( ) ) « This method gives the filter an opportunity to clean up any resources that are being held (for example, memory, file handles, threads)»( code source de javax.servlet.Filter), nous permet de libérer nos resources.

Dans cet exemple, le filter a une action externe à la resource, car la page demandée n’est pas modifiée. On effectue une action avant et après l’url demandée, mais on ne modifie pas le contenu de l’url. Il est cependant possible de le faire, nous le verrons dans le prochain exemple.

B) Cas d’un filtre qui modifie la réponse

On veut faire un filtre qui remplace tous les « bonjour » de la page demandée, en « good morning ».

Created with colorer-take5 library. Type 'java'

public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain)
    throws IOException, ServletException {

    
    PrintWriter out = response.getWriter();

    
    CharResponseWrapper wrapper = new CharResponseWrapper(
               (HttpServletResponse)response);

    chain.doFilter(request, wrapper);    
    
    String strAvant = wrapper.toString();

    String strApres = avant.replace("bonjour", "good morning");

    
    out.write(strApres);
    out.close();

    
}


Et la classe CharResponseWrapper correspondante :

Created with colorer-take5 library. Type 'java'

import java.io.CharArrayWriter;
import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

public class CharResponseWrapper extends
HttpServletResponseWrapper {
private CharArrayWriter output;

public String toString() {
return output.toString();

}

public CharResponseWrapper(HttpServletResponse response){
super(response);

           output = new CharArrayWriter();
}

public PrintWriter getWriter(){

           return new PrintWriter(output);
}
}



Cet exemple est inspiré de http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Servlets8.html .

On donne au doChain l’objet wrapper pour nous répondre. Cet objet définit lui-même la méthode getWriter. Ainsi à chaque fois que l’on utilisera notre objet wrapper pour nous répondre, on utilisera son PrintWriter à lui. Possédant le PrintWriter, qui est un CharArrayWriter en réalité (appelé « output »), on n’aura qu’à appeler la méthode toString de ce CharArrayWriter, pour obtenir tout ce qui a été écrit avec celui-ci.
Il suffit d’effectuer, après l’appel à doChain, String strAvant=wrapper.toString (on a définit la méthode toString comme étant output.toString).

On effectue le traitement voulu sur la string strAvant, c'est-à-dire remplacer les « bonjour », par des « good morning ».
Avec le PrintWriter, appelé out, qu’on a obtenu depuis l’objet response initial qu’on nous avez donné, on fait out.write(strApres), puis out.close( ). En effet, l’objet response qu’on nous avez donné comme paramètre à notre doPost, est fait pour qu’on exprime notre réponse.

RETOUR HAUT