1. Filtre servlet
1.1 Qu'est-ce qu'un filtre
Un filtre est un programme qui s'exécute sur le serveur avant le servlet ou la page JSP qui lui est associé. Les filtres peuvent être joints à un ou plusieurs servlets ou pages JSP et peuvent vérifier les informations de demande en entrant ces ressources. Après cela, le filtre peut être sélectionné comme suit:
① Appelez les ressources de manière régulière (c'est-à-dire appeler des servlets ou des pages JSP).
② Utilisez les informations de demande modifiées pour appeler la ressource.
③Allez la ressource, mais modifiez-la avant d'envoyer la réponse au client.
④Bloquez l'appel de ressource et accédez à une autre ressource, renvoyez un code d'état spécifique ou générez une sortie de remplacement.
1.2 Principes de base du filtre servlet
Lorsqu'un servlet est utilisé comme filtre, il peut traiter les demandes des clients. Une fois le traitement terminé, il sera remis au filtre suivant pour le traitement, afin que la demande du client soit traitée une par une dans la chaîne de filtre jusqu'à ce que la demande soit envoyée à la cible. Par exemple, un site Web a une page Web qui soumet "les informations d'enregistrement modifiées". Une fois que l'utilisateur a rempli les informations modifiées et l'a soumise, le serveur doit effectuer deux tâches lors du traitement: déterminez si la session du client est valide; et codent uniformément les données soumises. Ces deux tâches peuvent être traitées dans une chaîne de filtre composée de deux filtres. Lorsque le processus de filtre réussit, les données soumises sont envoyées à l'objectif final; Si le processus de filtre est échoué, la vue sera distribuée à la page d'erreur spécifiée.
2. Étapes de développement du filtre des servlet
Les étapes pour développer un filtre servlet sont les suivantes:
① Écrivez une classe de servlet qui implémente l'interface de filtre.
②Configure Filtre dans web.xml.
Le développement d'un filtre nécessite l'implémentation de l'interface de filtre. L'interface du filtre définit les méthodes suivantes:
① destory () est appelé par le conteneur Web pour initialiser ce filtre.
② init (filterconfig filterConfig) est appelé par le conteneur Web pour initialiser ce filtre.
③ DOFILTER (ServLetRequest Request, ServletResponse Response, filterchain) Code de traitement de filtrage spécifique.
3. Un exemple de cadre de filtre
SimpleFilter1.java
package com.zj.sample; importer java.io.ioexception; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletException; import javax.serserRegrode; classe publique SimpleFilter1 implémente Filter {@SuppressWarnings ("inutilisé") FilterConfig privé FilterConfig; public void init (filterConfig config) lève Servlexception {this.filterConfig = config; } public void dofilter (request de servletRequest, réponse servletResponse, chaîne de filterchain) {try {System.out.println ("dans SimpleFilter1: filtrage de la demande ..."); chain.dofilter (demande, réponse); // Envoyez le traitement au Système de filtre suivant.out .println ("dans SimpleFilter1: filtrage de la réponse ..."); } catch (ioException ioe) {ioe.printStackTrace (); } catch (servlexception se) {se.printStackTrace (); }} public void destre () {this.filterConfig = null; }}
SimpleFilter2.java
package com.zj.sample; importer java.io.ioexception; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletException; import javax.serserRegrode; classe publique SimpleFilter2 implémente Filter {@SuppressWarnings ("inutilisé") FilterConfig privé FilterConfig; public void init (filterConfig config) lève Servlexception {this.filterConfig = config; } public void dofilter (ServLetRequest Request, servletResponse réponse, filterchain chaîne) {try {System.out.println ("dans SimpleFilter2: filtrage de la demande ..."); chain.dofilter (demande, réponse); // Envoyez le traitement au Système de filtre suivant.out.println ("dans SimpleFilter2: filtrage de la réponse ..."); } catch (ioException ioe) {ioe.printStackTrace (); } catch (servlexception se) {se.printStackTrace (); }} public void destre () {this.filterConfig = null; }}
web.xml
<filter> <filter-name> filter1 </filter-name> <filter-class> com.zj.sample.simplefilter1 </filter-class> </filter> <filter-mapping> <filter-name> filter1 </filter-name> <url-sattern> / * </url-potendin> // Filter </filter-mapt> <filter> <filter-name> filter2 </ filter-name> <filter-class> com.zj.sample.simplefilter2 </filter-Class> </filter> <filter-mapping> <filter-name> filter2 </filter-name> <url-potern> / * </url-Pattern>
Ouvrez n'importe quelle page dans le conteneur Web pour sortir le résultat: (Remarquez l'ordre de demande / réponse exécuté par le filtre)
Dans SimpleFilter1: Filtrage de la demande ... dans SimpleFilter2: Filtrage de la demande ... dans SimpleFilter2: Filtrage de la réponse ... dans SimpleFilter1: Filtrage de la réponse ...
4. Filtre de rapport
Expérimentons avec un filtre simple qui imprime un message à la sortie standard en appelant le servlet ou la page JSP pertinent. Pour implémenter cette fonction, le comportement de filtrage est effectué dans la méthode Dofilter. Chaque fois qu'un servlet ou une page JSP associée à ce filtre est appelé, la méthode Dofilter génère une impression qui répertorie l'hôte demandé et l'URL de l'appel. Étant donné que la méthode GetRequesTurl est située dans le HttpServletRequest au lieu du serviltequest, l'objet ServLetRequest est construit comme type httpservletRequest. Changeons le SimpleFilter1.java dans le chapitre 3.
SimpleFilter1.java
package com.zj.sample; importer java.io.ioexception; import java.util.date; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletException; import javax.servlet.sservletRevest; javax.servlet.servletResponse; import javax.servlet.http.httpsservletRequest; classe publique SimpleFilter1 implémente Filter {@SuppressWarnings ("inutilisé") FilterConfig privé FilterConfig; public void init (filterConfig config) lève Servlexception {this.filterConfig = config; } public void dofilter (request de servletRequest, réponse servletResponse, chaîne de filterchain) {try {System.out.println ("dans SimpleFilter1: filtrage de la demande ..."); HttpServLetRequest req = (httpservletRequest); System.out.println (req.getReMoteHost () + "a essayé d'accéder" + req.getRequestUrl () + "sur" + new Date () + "."); chain.dofilter (demande, réponse); System.out.println ("dans SimpleFilter1: filtrage de la réponse ..."); } catch (ioException ioe) {ioe.printStackTrace (); } catch (servlexception se) {se.printStackTrace (); }} public void destre () {this.filterConfig = null; }}
Les paramètres Web.xml restent inchangés, dans le même chapitre 3.
test:
Entrez [url] http: // localhost: 8080 / test4jsp / login.jsp [/ url]
résultat:
Dans SimpleFilter1: Filtrage de la demande ... 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 1 J'ai essayé d'accéder à [url] http: // localhost: 8080 / test4jsp / login.jithin Simplefilter Sun MAR 04 SimpleFilter2: Filtrage de la réponse ... dans SimpleFilter1: Filtrage de la réponse ...
5. Filtres à l'accès (en utilisant des servlets pour initialiser les paramètres dans les filtres)
Ce qui suit est de définir une plage de temps d'accès normale en utilisant INIT pour enregistrer les accès qui ne sont pas dans cette période. Changeons le simpleFilter2.java dans le chapitre 3.
SimpleFilter2.java.
package com.zj.sample; import java.io.ioexception; import java.text.dateformat; import java.util.calendar; import java.util.gregoriancalendar; 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; import javax.servlet.http.httpservletRequest; classe publique SimpleFilter2 implémente Filter {@SuppressWarnings ("inutilisé") Config de filterConfig privé; Contexte privé ServletContext; Private int starttime, EndTime; Formateur de dateformat privé; public void init (filterConfig config) lève Servlexception {this.config = config; context = config.getServletContext (); formatter = dateFormat.getDateTimeInstance (dateFormat.Medium, DateFormat.Medium); Essayez {starttime = Integer.ParseInt (config.getInitParameter ("starttime")); // web.xml endtime = Integer.ParseInt (config.getInitParameter ("Bentime")); // web.xml} catch (NumberFormatexception nfe) {// MALFORME OR NULLUSUS // Défaut: accès à ou après 10 pm mais avant 6 AMS. starttime = 22; // 22:00 PM Fintime = 6; // 6:00 AM}} public void dofilter (requête servletRequest, réponse servletResponse, filterchain chaîne) {try {System.out.println ("dans SimpleFilter2: filtrage de la demande ..."); HttpServLetRequest req = (httpservletRequest); GregorianCalendar Calendar = New GregorianCalendar (); int currentTime = calendar.get (calendar.hour_of_day); if (isunusualtime (currenttime, starttime, endtime)) {context.log ("Warning:" + req.getRemoteHost () + "Consulté" + req.getRequesTurl () + "sur" + formatter.format (calendar.gettime ())); // Le fichier journal est sous <atalina_home> /logs.one journal par jour. } chain.dofilter (demande, réponse); System.out .println ("dans SimpleFilter2: filtrage de la réponse ..."); } catch (ioException ioe) {ioe.printStackTrace (); } catch (servlexception se) {se.printStackTrace (); }} public void destrement () {} // L'heure actuelle entre le début et la fin // des temps qui sont marqués comme des temps d'accès anormaux? Boolean privé IsunusualTime (int CurrentTime, int startTime, int fin) {// Si l'heure de début est inférieure à l'heure de fin (c'est-à-dire, //, ils sont deux fois le même jour), alors l'heure actuelle est considérée comme inhabituelle si elle est // entre les temps de début et de fin. if (startTime <endtime) {return ((currenttime> = startTime) && (currentTime <endtime)); } // Si l'heure de début est supérieure ou égale à l'heure de fin // (c'est-à-dire, l'heure de début est un jour et // l'heure de fin est le lendemain), alors l'heure actuelle // est considérée comme inhabituelle si elle n'est pas entre // les heures de fin et de début. else {return (! IsunusualTime (CurrentTime, Fintime, starttime)); }}}
Les paramètres Web.xml restent inchangés.
En ce qui concerne le traitement du journal Tomcat, voici une autre introduction. config.getServletContext (). Log ("Message de journal") rédigera des informations de journal dans le dossier <atalina_home> / logs. Le nom du fichier doit être localhost_log.2007-03-04.txt (un est généré par jour par date et peut être vu le lendemain). Pour obtenir un tel fichier journal, vous devriez avoir:
<Logger classname = "org.apache.catalina.logger.filelogger" prefix = "cataina_log." suffix = ". txt" himestamp = "true" />
6. Les filtres de site sont interdits
Si vous souhaitez interrompre le processus de filtrage ultérieur à mi-chemin lorsque votre filtre détecte une exception anormale, vous pouvez le faire:
Public void Dofilter (ServLetRequest Request, ServletResponse Response, FilterChain Chain) lève ServletException, ioException {httpServletRequest req = (httpServLetRequest) request; HttpServletResponse Res = (httpServletResponse) Réponse; if (isunusualCondition (req)) {res.sendRedirect ("http://www.somesite.com"); } else {chain.dofilter (req, res); }} L'exemple suivant est un filtre de site interdit. Si vous ne voulez pas que certains sites accédent à votre site Web, vous pouvez répertorier son site dans la valeur paramètre de web.xml, puis appliquer le principe ci-dessus pour sauter du filtrage régulier et donner la page interdite.
BannedAccessFilter.java
package com.zj.sample; import java.io.ioexception; import java.io.printwriter; import java.net.malformedUrlexception; import java.net.url; import java.util.hashset; import java.util.stringtokenizer; import javax.servlet.filter; import javax.sservlet.filterchain; import; javax.servlet.filterconfig; import javax.servlet.servletException; import javax.servlet.servletRequest; import javax.servlet.servletResponse; import javax.servlet.http.httpservletRequest; La classe publique BanNedAccessFilter implémente Filter {private hashset <string> BanNedSiteTable; / *** refuser l'accès si la demande provient d'un site banni ou est renvoyée ici * par un site banni. * / public void dofilter (ServLetRequest Request, ServletResponse Response, FilterChain Chain) lève ServletException, ioException {System.out.println ("dans BannedAccessFilter: filtrage de la demande ..."); HttpServLetRequest req = (httpservletRequest); String requestingHost = req.getRemoteHost (); String RefairingHost = getReferringHost (req.GetHeader ("référer")); String BanNedSite = null; booléen isbanned = false; if (BanNedSiteTable.Contains (DemandeingHost)) {BanNedSite = requestingHost; isbanned = true; } else if (BanNedSiteTable.Contains (RefairingHost)) {BanNedSite = RefairingHost; isbanned = true; } if (isBanned) {showwarning (réponse, banNSite); } else {chain.dofilter (demande, réponse); } System.out.println ("dans BanNedAccessFilter: filtrage de la réponse ..."); } / *** Créez un tableau de sites bancaires basés sur les paramètres d'initialisation. * N'oubliez pas que la version 2.3 de l'API Servlet oblige l'utilisation de la plate-forme * Java 2. Ainsi, il est sûr d'utiliser HashSet (qui détermine * si une clé donnée existe) plutôt que le HashTable Clumier * (qui a une valeur pour chaque clé). * / Public void init (FilterConfig Config) lève Servlexception {BanneRedSiteTable = new HashSet <string> (); String BanNedSites = config.getInitParameter ("BanNedSites"); // Ensemble de jetons par défaut: Espace blanc. StringTokenizer tok = new StringTokenizer (BanNedSites); while (tok.hasmoretokens ()) {String BanNedSite = tok.nextToken (); BanNedSiteTable.Add (BanNedSite); System.out.println ("Banned" + BannedSite); }} public void destrement () {} String privé getReferringHost (chaîne RefairingUrlString) {try {url ReforringUrl = new URL (ReFORERERRINGURLSTRING); return (regersurl.Gethost ()); } catch (MalformEdUrlexception Mue) {// malforme ou null return (null); }} // Réponse de remplacement qui est renvoyée aux utilisateurs // qui sont issues ou référées ici par un site de bannière. Private void showwarning (servletResponse Response, String BanNedSite) lève ServletException, ioException {réponse.SetContentType ("Text / Html"); Printwriter out = réponse.getWriter (); String docType = "<! Doctype html public /" - // w3c // dtd html 4.0 "+" transitional // en / "> / n"; Out.println (doctype + "<html> / n" + "<adre> <tight> Accès interdit </ title> </ head> / n" + "<corps bgcolor = /" blanc / "> / n" + "<h1> Accès interdit </ h1> / n" + "désolé, ou non" + bannedSite + "/ n" + "est autorisé" + via "+ bannedSite +" / n "+" est autorisé "+ via" + bannedSite + "/ n" + "est autorisé" + via "+ BannedSite +" / n "+" est autorisé. "</ Body> </html>"); }}
web.xml
<filter> <filter-name> BannedAccessFilter </ Filter-Name> <Lilter-Class> com.zj.sample.bannedaccessFilter </filter-Class> <Init-Param> <AmAn-Name> BannedSites </ Param-Name> <AmAr-Value> [URL] www.comPETISTISITE.COM [/ url] [url] www.bettersite.com [/ url] [url] www.moreservlets.com [/ url] 127.0.0.1//we tester ce </ param-value> </itnit-paam> </filter> <filter-mapping> <filter-name> BannedAccessFilter </filter-Name> <url-sattern> / * </ url-stern> </ filter-mapping>
test:
[url] http: // localhost: 8080 / test4jsp / [/ url]
résultat:
7. Remplacer le filtre
7.1 Modifier la réponse
Les filtres peuvent bloquer l'accès aux ressources ou les empêcher d'être activés. Mais si le filtre veut modifier la réponse générée par la ressource. Ce qu'il faut faire? Il ne semble pas y avoir de moyen d'accéder à la réponse générée par une ressource. Le deuxième paramètre de DoFilter (servletResponse) fournit un moyen d'envoyer une nouvelle sortie au client, mais ne fournit pas au filtre un moyen d'accéder à la sortie de la page servlet ou JSP. Pourquoi cela se produit-il? Parce que la page servlet ou jsp n'a même pas été exécutée lorsque la méthode Dofilter est appelée pour la première fois. Une fois que la méthode Dofilter dans l'objet FilterChain est appelée, il semble trop tard pour modifier la réponse, à savoir que les données ont été envoyées au client.
Cependant, il existe un moyen, c'est-à-dire modifier l'objet de réponse de la méthode Dofilter transmise à l'objet FilterChain. Généralement, créez un cache de toutes les versions de sortie générées par un servlet ou une page JSP. Servlet API version 2.3 fournit une ressource utile pour cela, à savoir la classe httpservletResponseWrapper. L'utilisation de cette classe comprend les cinq étapes suivantes:
1) Créez un wrapper de réponse. Étendre javax.servlet.http.httpservletResponsewrapper.
2) Fournissez un imprimeur qui cache la sortie. Surchargez la méthode GetWriter, renvoyez un Printwriter qui enregistre tout ce qui lui est envoyé et enregistre le résultat dans un champ accessible plus tard.
3) Passez cet emballage à Dofilter. Cet appel est légal car httpservletResponsewrapper implémente httpservletResponse.
4) Extraire et modifier la sortie. Après avoir appelé la méthode Dofilter de FilterChain, la sortie de la ressource d'origine peut être obtenue en utilisant le mécanisme fourni à l'étape 2. Vous pouvez le modifier ou le remplacer tant qu'il convient à votre application.
5) Envoyez la sortie modifiée au client. Étant donné que la ressource d'origine n'envoie plus de sorties au client (ces sorties sont déjà stockées dans votre wrapper de réponse), ces sorties doivent être envoyées. De cette façon, votre filtre doit obtenir un Printwriter ou OutputStream de l'objet de réponse d'origine et passer la sortie modifiée dans le flux.
7.2 Un emballage de réponse réutilisable
L'exemple suivant donne un wrapper qui peut être utilisé dans la plupart des applications où le filtre souhaite modifier la sortie de la ressource. La classe CharArayWrapper surcharge la méthode GetWriter pour renvoyer un imprimé qui accumule tout dans un grand tableau de caractères. Les développeurs peuvent obtenir ce résultat en utilisant TOCHARARRAY (char []) ou ToString (une chaîne dérivée de char []).
Chararraywrapper.java
package com.zj.sample; import java.io.charArrayWriter; import java.io.printwriter; import javax.servlet.http.httpservletResponse; import javax.servlet.http.httpservletResponsewrapper; / ** * Un wrapper de réponse qui prend tout ce que le client sortira normalement * et l'enregistre dans un seul tableau de caractères. * / classe publique Chararraywrapper étend httpServletResponseWrapper {private chararraywriter charwriter; / ** * Initialise le wrapper. * <p> * Tout d'abord, ce constructeur appelle le constructeur parent. Cet appel * est cruel pour que la réponse soit stockée et donc Setheader, * setstatus, addcookie, et ainsi de suite fonctionnent normalement. * <p> * Deuxièmement, ce constructeur crée un chararraywriter qui sera * utilisé pour accumuler la réponse. * / public chararraywrapper (réponse httpServletResponse) {super (réponse); charwriter = new chararraywriter (); } / ** * Lorsque les servlets ou les pages jsp demandent l'écrivain, ne leur donnez pas * le vrai. Au lieu de cela, donnez-leur une version qui écrit dans * le tableau de caractères. * Le filtre doit envoyer le contenu du tableau au * client (peut-être après l'avoir modifié). * / public printwriter getWriter () {return (new PrintWriter (charwriter)); } / ** * Obtenez une représentation de chaîne de l'ensemble du tampon. * <p> * assurez-vous <b> pas </b> pour appeler cette méthode plusieurs fois sur le même * wrapper. L'API de CharArayWriter ne garantit pas qu'il * "se souvient" de la valeur précédente, donc l'appel est susceptible de faire * une nouvelle chaîne à chaque fois. * / public String toString () {return (charwriter.toString ()); } / ** Obtenez le tableau de caractères sous-jacent. * / public char [] tocharArray () {return (charwriter.tocharArray ()); }}
7.3 Remplacer le filtre
Voici une application courante de CharArayWrapper donné dans la section précédente: Modification d'un filtre pour une chaîne cible multiple en une chaîne de substitut.
7.3.1 Filtre de remplacement général
RemplaceFilter.java donne un filtre qui enveloppe la réponse dans ChararraryWrapper, passe l'emballage dans la méthode Dofilter de l'objet FilterChain, extrait une valeur de type chaîne donnant la sortie de toutes les ressources, remplace toutes les occurrences d'une chaîne cible par une chaîne de substitution et envoie le résultat modifié au client.
Il y a deux choses à noter sur ce filtre. Tout d'abord, c'est une classe abstraite. Pour l'utiliser, vous devez créer une sous-classe qui fournit la mise en œuvre des méthodes GetTargetString et GetReplacementString. Un exemple de ce traitement est donné dans la sous-section suivante. Deuxièmement, il utilise une classe de services publics plus petite (voir filterUtils.java) pour le remplacement réel de la chaîne. Vous pouvez utiliser de nouveaux packages d'expression réguliers au lieu d'utiliser des méthodes de bas niveau et fastidieuses dans String et StringTokenizer.
Remplacefilter.java
package com.zj.sample; import java.io.ioexception; import java.io.printwriter; import javax.servlet.filter; import javax.servlet.filterchain; import javax.servlet.filterconfig; import javax.servlet.servletException; import javax.servlet.sservletRerest; javax.servlet.servletResponse; import javax.servlet.http.httpservletResponse; / ** * Filtre qui remplace toutes les occurrences d'une chaîne donnée avec un * remplacement. * Ceci est une classe abstraite: vous <i> doit </i> remplacer les méthodes GetTargetString * et GetReplacementString dans une sous-classe. * La première de ces méthodes spécifie la chaîne dans la réponse * qui doit être remplacée. La seconde de ces spécifications la chaîne * qui devrait remplacer chaque occurrence de la chaîne cible. * / classe abstraite publique RemplaceFilter implémente Filter {Private FilterConfig Config; Public void Dofilter (ServLetRequest Request, ServletResponse Response, FilterChain Chain) lève ServletException, ioException {CharArayWrapper ResponseWrapper = new CharArayWrapper ((httpservletResponse) Réponse); // Invoquez une ressource, accumulant la sortie dans l'emballage. chain.dofilter (demande, réponsewrapper); // transforme toute la sortie en une seule grande chaîne. String ResponseString = réponsewrapper.toString (); // En sortie, remplacez toutes les occurrences de chaîne cible par la chaîne de remplacement //. ResponseString = filterUtils.replace (ResponseString, getTargetString (), getReplacementString ()); // Mette à jour l'en-tête de longueur de contenu. Mise à jour (réponse, réponse); Printwriter out = réponse.getWriter (); out.write (ResponseString); } / ** * Stockez l'objet FilterConfig dans le cas où les sous-classes le souhaitent. * / public void init (filterConfig config) lève Servlexception {this.config = config; } protégée filterConfig getFilterConfig () {return (config); } public void destrement () {} / ** * La chaîne qui doit être remplacée. * Remplacez cette méthode dans votre sous-classe. * / public abstrait string getTargetString (); / ** * La chaîne qui remplace la cible. Remplacez cette méthode dans * votre sous-classe. * / Public Abstract String getReplacementString (); / ** * met à jour les en-têtes de réponse. Cette version simple définit simplement * l'en-tête de longueur de contenu, en supposant que nous utilisons un jeu de caractères * qui utilise 1 octet par caractère. * / public void updateHeaders (servLetResponse Response, String ResponseString) {réponse.setContentLength (ResponseString.Length ()); }}
FilterUtils.java
package com.zj.sample; / ** * Petite utilitaire pour aider aux emballages de réponse qui retournent les chaînes. * / classe publique FilterUtils {/ ** * Modifiez toutes les occurrences d'ORIG dans la mainstring à remplacer. * / public static String remplace (String mainstring, string orig, string remplacement) {string result = ""; int oldindex = 0; int index = 0; int origlength = orig.length (); while ((index = mainstring.indexof (orig, oldindex))! = -1) {result = result + mainstring.substring (oldindex, index) + remplacement; OldIndex = index + origlengle; } result = result + mainstring.substring (oldIndex); retour (résultat); }} 7.3.2 Implémentez un filtre de remplacement de caractères. Supposons que Baidu ait acquis Google (juste une hypothèse), tous les textes avec le mot Google sur toutes les pages doivent être remplacés par Baidu! ReplaceSItenameFilter.java hérite du RemplaceFilter.java ci-dessus pour implémenter cette fonction. RemplaceSItenameFilter.javapackage com.zj.sample; La classe publique RemplaceSiTenameFilter étend RemplaceFilter {public String getTargetString () {return ("google.com.cn"); } public String getReplacementString () {return ("baidu.com"); }}
web.xml
<filter> <filter-name> ReplateSItenameFilter </ Filter-Name> <Filter-Class> com.zj.sample.replaceSiteNameFilter </ Filter-Class> </filter> <Filter-Mapping> <Filter-Name> ReplateSiteNameFilter </ Filter-Name> <Url-Pattern> / Login.jsp </ Url-Patter>
Résultats des tests:
Avant le filtrage
Après filtrage
8. Filtre de compression
Il existe plusieurs derniers navigateurs qui peuvent gérer le contenu compressé, déballer automatiquement le fichier compressé avec GZIP comme valeur d'en-tête de réponse en codage de contenu, puis traitez les résultats comme le document d'origine. L'envoi d'un tel contenu compressé peut gagner beaucoup de temps, car le temps nécessaire pour compresser un document sur le serveur, puis annuler le document sur le client est trivial par rapport au temps nécessaire pour télécharger le fichier. Le programme Longservlet.java donne un servlet avec une longue sortie de texte brut en double, un servlet mature de compression. Si vous utilisez GZIP, il peut compresser la sortie à 1/300!
Lorsque le navigateur prend en charge cette capacité de compression, le filtre de compression peut utiliser le chararraywrapper introduit au chapitre 7 pour compresser le contenu. Le contenu suivant est nécessaire pour terminer cette tâche:
1) Classe qui implémente l'interface du filtre. Cette classe est nommée CompressionFilter. La méthode INIT stocke l'objet FilterConfig dans un champ au cas où la sous-classe doit accéder à l'environnement servlet ou au nom de filtre. Le corps de la méthode destory est vide.
2) L'objet de réponse enveloppé. La méthode Dofilter enveloppe l'objet ServletResponse dans un chararraywrapper et transmet ce wrapper sur la méthode Dofilter de l'objet FilterChain. Une fois cet appel terminé, tous les autres filtres et ressources finales ont été exécutés et la sortie est dans l'emballage. De cette façon, le Dofilter d'origine extrait un tableau de caractères représentant la sortie de toutes les ressources. Si le client indique qu'il prend en charge la compression (c'est-à-dire la prise de GZIP comme valeur pour l'en-tête d'acceptation), le filtre ajoute un gzipOutStream vers le bytearrayoutputStream, copiez le tableau de caractères dans ce flux et définit l'en-tête de réponse d'encodage de contenu vers GZIP. Si le client ne prend pas en charge GZIP, copiez le tableau de caractères non modifié sur ByteArrayOutputStream. Enfin, DoFilter envoie le résultat au client en écrivant l'intégralité du tableau de caractères (probablement compressé) dans le SUTPUTSTREAM associé à la réponse d'origine.
3) Enregistrez le Longservlet.
Compressionfilter.java
package com.zj.sample; importer java.io.bytearrayoutputStream; import java.io.ioexception; import java.io.outputstream; import java.io.outputstreamwriter; import java.util.zip.gzipoutputStream; import javax.servlet.filter; import javax.sservlet.filterchain; javax.servlet.filterconfig; import javax.servlet.servletException; importer javax.servlet.servletRequest; import javax.servlet.servletResponse; import javax.servlet.http.httpservletRegresserrest; import; / ** * Filtrez qui compresse la sortie avec GZIP (en supposant que le navigateur prend en charge * GZIP). * / public class compressionFilter implémente filter {private filterConfig config; / ** * Si le navigateur ne prend pas en charge GZIP, appelez normalement la ressource. Si Browser * <i> fait </i> prendre en charge GZIP, définissez l'en-tête de réponse en codage de contenu et * Invoquez une ressource avec une réponse enveloppée qui collecte toute la sortie. * Extraire la sortie et l'écrivez-la dans un tableau d'octets gzippé. Enfin, écrivez * ce tableau au flux de sortie du client. * / public void dofilter (ServLetRequest Request, servletResponse réponse, filterchain chaîne) lève ServletException, ioException {httpServletRequest req = (httpServletRequest) request; HttpServletResponse Res = (httpServletResponse) Réponse; if (! isGzipSupported (req)) {// Invoquez la ressource normalement. chaîne.Dofilter (req, res); } else {// Dites le navigateur que nous l'envoyons des données gziées. res.sethEader ("contenu-codage", "gzip"); // Invoquez une ressource, accumulant la sortie dans l'emballage. CharArrayWrapper ResponseWrapper = new CharArayWrapper (RES); chain.dofilter (req, réponsewrapper); // Obtenez un tableau de caractères représentant la sortie. char [] ResponseChars = réponsewrapper.tocharay (); // Faire un écrivain qui comprime les données et les met dans un tableau d'octets. ByteArrayOutputStream bytestream = new bytearrayoutputStream (); GzipOutputStream zipout = new gzipOutputStream (bytestream); OutputStreamWriter tempout = new OutputStreamWriter (zipout); // Compressez la sortie d'origine et placez-la dans le tableau d'octets. tempout.write (ResponseChars); // Les flux GZIP doivent être explicitement fermés. tempout.close (); // Mette à jour l'en-tête de longueur de contenu. res.setContentLength (bytestream.size ()); // Envoyez le résultat compressé au client. OutputStream realout = res.getOutputStream (); bytestream.writeto (realout); }} / ** * Stockez l'objet FilterConfig dans le cas où les sous-classes le souhaitent. * / public void init (filterConfig config) lève Servlexception {this.config = config; } protégée filterConfig getFilterConfig () {return (config); } public void destre () {} private booléen isGzipSupported (httpServLetRequest req) {String BrowseRencodings = req.GetHeader ("accepter-coding"); return ((BrowseRenCodings! = null) && (BrowseRendings.Indexof ("gzip")! = -1)); }} Longservlet.javapackage com.zj.sample; import java.io.ioexception; import java.io.printwriter; import javax.servlet.servletException; import javax.servlet.http.httpleservlet; import javax.servlet.http.http.httpleservlet; import; javax.servlet.http.httpservletResponse; / ** * servlet avec <b> Sortie </b> longue. Utilisé pour tester l'effet du filtre de compression * du chapitre 9. * / La classe publique Longservlet étend HttpServlet {public void Doget (HttpServletRequest Request, HttpservletResponse Response) lève ServletException, ioException {réponse.SetContentType ("Text / html"); Printwriter out = réponse.getWriter (); String docType = "<! Doctype html public /" - // w3c // dtd html 4.0 "+" transitional // en / "> / n"; String title = "Long Page"; out.println (doctype + "<html> / n" + "<éad- head> <itle>" + title + "</ title> </ head> / n" + "<corps bgcolor = /" # fdf5e6 / "> / n" + "<h1 align = /" Center / ">" + title + "</ h1> / n"); String line = "blah, bla, bla, bla, bla." + "Yadda, yadda, yadda, yadda."; pour (int i = 0; i <10000; i ++) {out.println (ligne); } out.println ("</ body> </html>"); }}
web.xml
<filter> <filter-name> CompressionFilter </filter-name> <filter-class> com.zj.sample.compressionfilter </filter-class> </filter> <filter-mapping> <filter-name> compressionFilter </filter-name> <sterplet-name> <Servlet-Name> Longservlet </ servlet-name> <servlet-class> com.zj.sample.longservlet </ servlet-class> </ servlet> <servlet-mapping> <servlet-name> Longservlet </ servlet-name> <Url-Pattern> / LongServlet </url-Pattern> </ serplet-mapping>