2010-07-30 3 views
10

Est-ce que quelqu'un sait comment coder un filtre de servlet qui va définir les en-têtes de cache sur une réponse pour un type de fichier/contenu donné? J'ai une application qui sert beaucoup d'images, et je voudrais réduire la bande passante pour l'héberger en faisant en sorte que le navigateur cache ceux qui ne changent pas très souvent. Idéalement, j'aimerais pouvoir spécifier un type de contenu et lui faire définir les en-têtes appropriés chaque fois que le type de contenu correspond.Filtre de servlet pour la mise en cache du navigateur?

Est-ce que quelqu'un sait comment s'y prendre? Ou, mieux encore, avoir un exemple de code qu'ils seraient prêts à partager? Merci!

Répondre

15

Dans votre filtre ont cette ligne:

chain.doFilter(httpRequest, new AddExpiresHeaderResponse(httpResponse)); 

Lorsque l'enveloppe de réponse ressemble à:

class AddExpiresHeaderResponse extends HttpServletResponseWrapper { 

    public static final String[] CACHEABLE_CONTENT_TYPES = new String[] { 
     "text/css", "text/javascript", "image/png", "image/jpeg", 
     "image/gif", "image/jpg" }; 

    static { 
     Arrays.sort(CACHEABLE_CONTENT_TYPES); 
    } 

    public AddExpiresHeaderResponse(HttpServletResponse response) { 
     super(response); 
    } 

    @Override 
    public void setContentType(String contentType) { 
     if (contentType != null && Arrays.binarySearch(CACHEABLE_CONTENT_TYPES, contentType) > -1) { 
      Calendar inTwoMonths = GeneralUtils.createCalendar(); 
      inTwoMonths.add(Calendar.MONTH, 2); 

      super.setDateHeader("Expires", inTwoMonths.getTimeInMillis()); 
     } else { 
      super.setHeader("Expires", "-1"); 
      super.setHeader("Cache-Control", "no-store, no-cache, must-revalidate"); 
     } 
     super.setContentType(contentType); 
    } 
} 

En bref, cela crée une enveloppe de réponse, qui, sur la définition du type de contenu, ajoute l'en-tête expire. (Si vous le souhaitez, vous pouvez également ajouter les autres en-têtes dont vous avez besoin). J'ai utilisé ce filtre + wrapper et cela fonctionne.

See this question sur un problème spécifique que cela résout, et la solution originale par BalusC.

+3

Sinon, si vous avez tous ces fichiers dans un dossier commun, par exemple '/ static', il suffit de mapper le filtre sur un' url-pattern' de '/ static/*' de sorte que vous n'ayez pas besoin de vérifier le type de contenu à chaque fois et que vous pouvez simplement définir les en-têtes de réponse directement. – BalusC

+0

Cela ne fonctionnera PAS pour les ressources SSL/TLS sur GlassFish car le conteneur ajoute automatiquement les en-têtes Pragma et Cache-Control. Si vous souhaitez mettre en cache ces ressources, vous devez supprimer/remplacer ces en-têtes avec quelque chose comme: super.setHeader ("Pragma", null); et super.setHeader ("Cache-Control", null). Cache-Control: "public" fonctionnerait probablement aussi. Remarque: L'utilisation de null peut ne pas être portable car elle n'est pas dans la spécification. Il peut y avoir un moyen de désactiver le conteneur d'ajouter les en-têtes, mais il n'est pas bien documenté. – Ryan

Questions connexes