1. Filtro de servlet
1.1 ¿Qué es un filtro?
Un filtro es un programa que se ejecuta en el servidor antes de la página Servlet o JSP asociada con él. Los filtros se pueden adjuntar a uno o más servlets o páginas JSP y pueden verificar la información de la solicitud que ingresa estos recursos. Después de esto, el filtro se puede seleccionar de la siguiente manera:
① Llame a los recursos de una manera regular (es decir, llame a servlets o páginas JSP).
② Use la información de solicitud modificada para llamar al recurso.
③Tive el recurso, pero modifíquelo antes de enviar la respuesta al cliente.
④ Inmoce la llamada de recursos y, en su lugar, vaya a otro recurso, devuelva un código de estado específico o genere una salida de reemplazo.
1.2 Principios básicos del filtro de servlet
Cuando se usa un servlet como filtro, puede procesar las solicitudes de los clientes. Una vez completado el procesamiento, se entregará al siguiente filtro para su procesamiento, de modo que la solicitud del cliente se procese una por una en la cadena de filtro hasta que la solicitud se envíe al objetivo. Por ejemplo, un sitio web tiene una página web que envía "información de registro modificada". Después de que el usuario llena la información modificada y la envía, el servidor debe hacer dos tareas al procesar: determinar si la sesión del cliente es válida; y codifica de manera uniforme los datos enviados. Estas dos tareas se pueden procesar en una cadena de filtros compuesta por dos filtros. Cuando el proceso de filtro es exitoso, los datos enviados se envían al objetivo final; Si el proceso de filtro no tiene éxito, la vista se distribuirá a la página de error especificada.
2. Pasos de desarrollo del filtro de servlet
Los pasos para desarrollar un filtro de servlet son los siguientes:
① Escriba una clase Servlet que implementa la interfaz de filtro.
② Filtro de configuración en web.xml.
Desarrollar un filtro requiere implementar la interfaz de filtro. La interfaz de filtro define los siguientes métodos:
① El contenedor web llama a Destory () para inicializar este filtro.
② El contenedor web llama a Init (FilterConfig FilterConfig) para inicializar este filtro.
③ Solicitud de Dofilter (ServletRequest, Respuesta de ServletResponse, FilterChain Chain) Código de procesamiento de filtrado específico.
3. Un ejemplo de un marco de filtro
Simplefilter1.java
package com.zj.sample;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse; public class SimpleFilter1 implementa filtro {@suppleswarnings ("sin usar") FilterConfig privado FilterConfig; public void init (filterconfig config) lanza ServletException {this.filterconfig = config; } public void dofilter (ServletRequest Solicitud, Respuesta ServletResponse, FilterChain Chain) {try {System.out.println ("dentro de SimpleFilter1: Filtrando la solicitud ..."); Chain.dofilter (solicitud, respuesta); // Envíe el procesamiento al siguiente filtro System.out .println ("dentro de SimpleFilter1: Filtrando la respuesta ..."); } catch (ioException IOE) {ioe.printstacktrace (); } catch (ServLetException SE) {SE.PrintStackTrace (); }} public void destruye () {this.filterConfig = null; }}
Simplefilter2.java
package com.zj.sample;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse; public class SimpleFilter2 Implementa Filter {@SupplesSWarnings ("no utilizado") FilterConfig privado FilterConfig; public void init (filterconfig config) lanza ServletException {this.filterconfig = config; } public void dofilter (solicitud de servletRequest, respuesta servletResponse, cadena de filtro de filtro) {try {System.out.println ("dentro de SimpleFilter2: Filtrando la solicitud ..."); Chain.dofilter (solicitud, respuesta); // Envía el procesamiento al siguiente filtro System.out.println ("dentro de SimpleFilter2: Filtrando la respuesta ..."); } catch (ioException IOE) {ioe.printstacktrace (); } catch (ServLetException SE) {SE.PrintStackTrace (); }} public void destruye () {this.filterConfig = null; }}
web.xml
<filter> <filter-name> filtre1 </filtre-name> <filter-class> com.zj.sample.simplefilter1 </filter-class> </filter> <filter-mapping> <filter-name> filtre1 </filtre-name> <url-pattern>/*</url-pattern-pattern // filter </filtre-mapping> <filter-name> filtre2 <//name> <Tarter-class> com.zj.sample.simplefilter2 </filter-class> </filtre> <filter-mapping> <filter-name> filtro2 </filtre-name> <url-pattern>/*</ url-pattern> // filtro para todas las visitas </filtro-mapping>
Abra cualquier página en el contenedor web para generar el resultado: (Tenga en cuenta el orden de solicitud/respuesta ejecutado por el filtro)
Dentro de SimpleFilter1: Filtrando la solicitud ... dentro de SimpleFilter2: Filtrando la solicitud ... dentro de SimpleFilter2: Filtrando la respuesta ... dentro de SimpleFilter1: Filtrando la respuesta ...
4. Filtro de informes
Experimentemos con un filtro simple que imprime un mensaje para la salida estándar llamando a la página Servlet o JSP relevante. Para implementar esta función, el comportamiento de filtrado se realiza en el método Dofilter. Cada vez que se llama a una página de servlet o JSP asociada con este filtro, el método Dofilter genera una impresión que enumera el host solicitado y la URL de la llamada. Debido a que el método GetRequesturl se encuentra en el HttpServletRequest en lugar del ServLetRequest, el objeto ServLetRequest se construye como el tipo HttPservletRequest. Cambiemos el SimpleFilter1.java en el Capítulo 3.
Simplefilter1.java
paquete com.zj.sample; import 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.servletReCest; javax.servlet.servletResponse; import javax.servlet.http.httpservletRequest; public class SimpleFilter1 implementa filtro {@suppleswarnings ("sin usar") FilterConfig privado FilterConfig; public void init (filterconfig config) lanza ServletException {this.filterconfig = config; } public void dofilter (ServletRequest Solicitud, Respuesta ServletResponse, FilterChain Chain) {try {System.out.println ("dentro de SimpleFilter1: Filtrando la solicitud ..."); HttpservletRequest req = (httpservletRequest) solicitud; System.out.println (req.getRemoteHost () + "intenté acceder a" + req.getRequestUrl () + "en" + nueva fecha () + "."); Chain.dofilter (solicitud, respuesta); System.out.println ("dentro de SimpleFilter1: Filtrando la respuesta ..."); } catch (ioException IOE) {ioe.printstacktrace (); } catch (ServLetException SE) {SE.PrintStackTrace (); }} public void destruye () {this.filterConfig = null; }}
La configuración web.xml permanece sin cambios, en el mismo capítulo 3.
prueba:
Ingrese [url] http: // localhost: 8080/test4jsp/login.jsp [/url]
resultado:
Dentro de SimpleFilter1: Filtrando la solicitud ... 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 0: 1 Intenté acceder a [url] http: // localhost: 8080/test4jsp/login.jsp [/url] en el sol 04 17:01:37 cst 2007.within simplefilter2: filtrando la solicitud ... dentro de la solicitud ... dentro de la solicitud ... dentro de Simplefilter2: Simplefilter La respuesta ... dentro de SimpleFilter1: Filtrando la respuesta ...
5. Filtros en el acceso (usando servlets para inicializar los parámetros en los filtros)
Lo siguiente es establecer un rango de tiempo de acceso normal utilizando AIT para registrar accesos que no están en este período de tiempo. Cambiemos el SimpleFilter2.Java en el Capítulo 3.
SimpleFilter2.Java.
paquete 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; javax.servlet.servletContext; import javax.servlet.servletException; import javax.servlet.servletRequest; import javax.servlet.servletResponse; import javax.servlet.http.httpservletRequest; public class SimpleFilter2 Implementa Filter {@SupplesSwarnings ("sin usar") configuración privada FilterConfig; Contexto privado de servletContext; Private int Starttime, Endtime; Formatero privado de dateFormat; public void init (filterconfig config) lanza ServletException {this.config = config; context = config.getServletContext (); formatter = dateFormat.getDateTimeInstance (dateFormat.Medium, dateFormat.Medium); Pruebe {starttime = integer.ParseInt (config.getInitParameter ("starttime")); // web.xml endtime = integer.parseInt (config.getInitParameter ("endtime")); // web.xml} capt (numberFormeXception nfe) {// malformado o null // predeterminado: acceso en o después de 10 pm pero antes de 6 ousual. starttime = 22; // 10:00 PM Endtime = 6; // 6:00 AM}} public void dofilter (ServletRequest Solicitud, respuesta de servicio de servicio, cadena FilterChain) {try {System.out.println ("dentro de SimpleFilter2: Filtrando la solicitud ..."); HttpservletRequest req = (httpservletRequest) solicitud; Calendario Gregoriancalendar = nuevo Gregoriancalendar (); int centreTtime = calendar.get (calendar.hour_of_day); if (isunusualTime (currenttime, starttime, endtime)) {context.log ("advertencia:" + req.getRemoteHost () + "accedido" + req.getRequesturl () + "on" + formatter.format (calendar.gettime ())); // El archivo de registro está en <Catalina_Home> /Logs.one Registro por día. } chain.dofilter (solicitud, respuesta); System.out .println ("dentro de simplyfilter2: filtrando la respuesta ..."); } catch (ioException IOE) {ioe.printstacktrace (); } catch (ServLetException SE) {SE.PrintStackTrace (); }} public void destruye () {} // ¿Es la hora actual entre el inicio y el final // tiempos que están marcados como tiempos de acceso anormales? Private boolean isunusualtime (int curtenttime, int starttime, int endtime) {// Si la hora de inicio es menor que la hora de finalización (es decir, // son dos veces el mismo día), entonces la hora actual se considera inusual si es // entre las horas de inicio y finalización. if (starttime <endtime) {return ((currenttime> = starttime) && (currenttime <endtime)); } // Si la hora de inicio es mayor o igual a la hora de finalización // (es decir, la hora de inicio está en un día y // la hora de finalización es al día siguiente), entonces la hora actual // se considera inusual si no está entre // el final y los tiempos de inicio. else {return (! ISUNUSUALTIME (CurrentTime, Endtime, Starttime)); }}}
La configuración web.xml permanece sin cambios.
Con respecto al procesamiento de registros de Tomcat, aquí hay una introducción adicional. config.getServletContext (). Log ("Mensaje de registro") escribirá información de registro en la carpeta <Catalina_Home>/Logs. El nombre del archivo debe ser localhost_log.2007-03-04.txt (uno se genera por día por fecha, y se puede ver al día siguiente). Para obtener un archivo de registro de este tipo, debe tener:
<Logger classname = "org.apache.catalina.logger.filelogger" prefix = "catalina_log". Suffix = ". txt" timestamp = "true"/>
6. Los filtros del sitio están prohibidos
Si desea interrumpir el proceso de filtrado posterior a mitad de camino cuando su filtro detecta una excepción anormal, puede hacer esto:
Public void dofilter (solicitud de servletRequest, respuesta de servicio de servicio, cadena de filtro de filtro) arroja servletException, ioexception {httpservletRequest req = (httpservletRequest) solicitud; HttpservletResponse Res = (httpservletResponse) respuesta; if (isunusualCondition (req)) {res.sendedirect ("http://www.somesite.com"); } else {chain.dofilter (req, res); }} El siguiente ejemplo es un filtro de sitio prohibido. Si no desea que algunos sitios accedan a su sitio web, puede enumerar su sitio en el valor de parámetro de Web.xml, y luego aplicar el principio anterior para saltar del filtrado regular y dar la página prohibida.
Bannedaccessfilter.java
paquete com.zj.sample; import java.io.ioException; import java.io.printwriter; import java.net.malFormedUrexception; import java.net.url; import java.util.hashset; import java.util.stringTokenizer; import javax.servlet.filter; import javax.servlet.servlet; javax.servlet.filterconfig; import javax.servlet.servletException; import javax.servlet.servletRequest; import javax.servlet.servletResponse; import javax.servlet.http.httpservletRequest; clase pública bannedAccessFilter implementa filtro {hashset privado <string> bannedSitTable; /*** Dene el acceso si la solicitud proviene de un sitio bannered o es referido aquí* por un sitio bannered. */ public void dofilter (solicitud de servletRequest, respuesta de servicio de servicio, cadena de filtro de filtro) lanza ServletException, ioexception {System.out.println ("dentro de BannedAccessFilter: filtrar la solicitud ..."); HttpservletRequest req = (httpservletRequest) solicitud; Cadena requestingHost = req.getRemoteHost (); Cadena referingHost = getReferringHost (req.getheader ("referente")); Cadena bannedsite = null; booleano isbanned = false; if (bannedSitTable.contains (requestinghost)) {bannedsite = requestingHost; isbanned = verdadero; } else if (bannedSitTable.contains (referingHost)) {bannedsite = referingHost; isbanned = verdadero; } if (isbanned) {showwarning (respuesta, bannedsite); } else {chain.dofilter (solicitud, respuesta); } System.out.println ("dentro de BannedAccessFilter: filtrar la respuesta ..."); } /*** Cree una tabla de sitios bannerados basados en los parámetros de inicialización.* Recuerde que la versión 2.3 de la API de Servlet exige el uso de la plataforma* Java 2. Por lo tanto, es seguro usar hashset (que determina* si existe una clave determinada) en lugar de la hashtable más torpe* (que tiene un valor para cada clave).*/ Public void init (filterconfig config) lanza ServletException {banneredSitable = new Hashset <string> (); String BannedSites = config.getInitParameter ("BannedSites"); // Conjunto de token predeterminado: espacio en blanco. StringTokenizer tok = new StringTokenizer (BannedSites); while (tok.hasmoretokens ()) {string bannedsite = tok.nextToken (); BannedSitTable.Add (BannedSite); System.out.println ("prohibido" + bannedsite); }} public void destruye () {} cadena privada getReferringHost (string refererringUrlString) {try {url referRingUrl = new url (referRingUrlString); return (referRingUrl.getHost ()); } catch (malformedurexception mue) {// retorno malformado o nulo (nulo); }} // Respuesta de reemplazo que se devuelve a los usuarios // que son o se refieren aquí por un sitio de banner. Private void showwarning (respuesta de servicio de servicio, cadena bannedsite) lanza ServletException, ioexception {Response.SetContentType ("Text/Html"); PrintWriter out = Response.getWriter (); Cadena doctype = "<! DocType html public/"-// w3c // dtd html 4.0 " +" transitional // en/">/n"; out.println (DocType + "<html>/n" + "<head> <title> Access Prohibited </title> </head>/n" + "<body bgcolor =/" white/">/n" + "<h1> Access Prohibited </h1>/n" + "Sorry, Access From o Via" + Bannedsite + "/n" + " +"/"/"/"/"/"/" ¿Se permite " +"/"/"/"/"/"/"/"/"/"/"/"/"/"/"/"/"/"/"/"no se permite/" + "/"/"/"/"/"/"/"/"/"/"/"/"/"/"/"/"/"/"no se deja/"/"/"/"/"/"/"/"/"/"/"/"no se permite/" + " +"/"/"/"/"/"/"/"/"/"/"/"/" no se permite/" +" + " "</body> </ html>"); }}
web.xml
<Scilt> <Sterry-Name> bannedAccessFilter </filter-name> <filter-class> com.zj.sample.bannedAccessfilter </filter-class> <init-param> <amamname> bannedsites <//mamam-value> [url] www.competingsite.com [/url] [url] wwww.bettersite. [URL] www.moreservlets.com [/url] 127.0.0.1//we Prueba esto </param-value> </initparam> </filtro> <filter-mapping> <filter-name> bannedaccessfilter </filtre-name> <url-pattern>/*</url-pattern> </filter-mapping>
prueba:
[url] http: // localhost: 8080/test4jsp/[/url]
resultado:
7. Reemplace el filtro
7.1 Modificar la respuesta
Los filtros pueden bloquear el acceso a los recursos o evitar que se activen. Pero si el filtro quiere cambiar la respuesta generada por el recurso. ¿Qué hacer? Parece que no hay forma de acceder a la respuesta generada por un recurso. El segundo parámetro de Dofilter (ServLetResponse) proporciona una forma de enviar una nueva salida al cliente, pero no proporciona al filtro una forma de acceder a la salida de la página Servlet o JSP. ¿Por qué está sucediendo esto? Porque la página Servlet o JSP ni siquiera se ha ejecutado cuando se solicita el método Dofilter por primera vez. Una vez que se llama el método Dofilter en el objeto FilterChain, parece demasiado tarde para modificar la respuesta, que es que los datos se han enviado al cliente.
Sin embargo, hay una manera, es decir, modificar el objeto de respuesta del método Dofilter pasado al objeto FilterChain. En general, cree un caché de todas las versiones de salida generadas por un servlet o página JSP. Servlet API Versión 2.3 proporciona un recurso útil para esto, a saber, la clase httpservletResponseWrapper. El uso de esta clase incluye los siguientes cinco pasos:
1) Cree un envoltorio de respuesta. Extender javax.servlet.http.httpservletResponsewrapper.
2) Proporcione un impreso impreso que almacena la salida. Sobrecarga el método GetWriter, devuelve un PrintWriter que guarde todo lo que se le envía y guarda el resultado en un campo al que se puede acceder más adelante.
3) Pase este envoltorio a Dofilter. Esta llamada es legal porque httpservletResponseWrapper implementa httpservletResponse.
4) Extraer y modificar la salida. Después de llamar al método Dofilter de FilterChain, la salida del recurso original se puede obtener utilizando el mecanismo proporcionado en el paso 2. Puede modificarlo o reemplazarlo siempre que sea adecuado para su aplicación.
5) Envíe la salida modificada al cliente. Debido a que el recurso original ya no envía salidas al cliente (estas salidas ya están almacenadas en su envoltorio de respuesta), se deben enviar estas salidas. De esta manera, su filtro necesita obtener un PrintWriter o OutputStream desde el objeto de respuesta original y pasar la salida modificada a la secuencia.
7.2 Un envoltorio de respuesta reutilizable
El siguiente ejemplo proporciona un envoltorio que se puede usar en la mayoría de las aplicaciones donde el filtro desea modificar la salida del recurso. La clase CharArrayWrapper sobrecarga el método GetWriter para devolver un PrintWriter que acumula todo en una matriz de personajes grandes. Los desarrolladores pueden obtener este resultado utilizando ToCarArray (Char [] original) o ToString (una cadena derivada de Char []).
CharArrayWrapper.java
paquete com.zj.sample; import java.io.chararraywriter; import java.io.printwriter; import javax.servlet.http.httpservletResponse; import javax.servlet.http.httpservletResponseWrapper; /** * Un envoltorio de respuesta que toma todo lo que el cliente normalmente * saldría y lo guarda en una gran matriz de personajes. */clase pública CharArrayWrapper extiende httpservletResponseWrapper {private CharArrayWriter Charwriter; /*** Inicializa Wrapper. * <P> * Primero, este constructor llama al constructor principal. Esa llamada *es cruel para que la respuesta se almacene y, por lo tanto, Setheader, *setstatus, addcookie, etc., el trabajo normalmente. * <p> * Segundo, este constructor crea un compatidor chararray que * se utilizará para acumular la respuesta. */ public CharArrayWrapper (respuesta httpServletResponse) {super (respuesta); charwriter = new CharArrayWriter (); } /*** Cuando los servlets o las páginas JSP piden al escritor, no les dé* el real. En cambio, dales una versión que escriba en* la matriz de personajes. * El filtro debe enviar el contenido de la matriz al cliente* (tal vez después de modificarlo). */ public PrintWriter getWriter () {return (new PrintWriter (charwriter)); } /*** Obtenga una representación de cadena de todo el búfer. * <p> * Asegúrese de <b> no </b> para llamar a este método varias veces en la misma * envoltura *. La API para CharArrayWriter no garantiza que * "recuerde" el valor anterior, por lo que es probable que la llamada sea * una nueva cadena cada vez. */ public string toString () {return (charwriter.toString ()); } /** Obtenga la matriz de personajes subyacente. */ public char [] toCarArray () {return (charwriter.toCarArray ()); }}
7.3 Reemplazar el filtro
Aquí hay una aplicación común de CharArrayWrapper dada en la sección anterior: Cambiar un filtro para una cadena de destino de múltiples economías a una cadena sustituta.
7.3.1 Filtro de reemplazo general
Reemplazarfilter.java proporciona un filtro que envuelve la respuesta en ChararRaryWrapper, pasa el envoltorio al método Dofilter del objeto FilterChain, extrae un valor de tipo de cadena que da la salida de todos los recursos, reemplaza todas las ocurrencias de una cadena de destino con una cadena de sustitución y envía el resultado modificado al cliente.
Hay dos cosas a tener en cuenta sobre este filtro. Primero, es una clase abstracta. Para usarlo, debe crear una subclase que proporcione la implementación de los métodos GetTargetString y GetReplacementsTring. Un ejemplo de este tratamiento se da en la siguiente subsección. En segundo lugar, utiliza una clase de utilidad más pequeña (ver FilterUtils.java) para el reemplazo de cadena real. Puede usar nuevos paquetes de expresión regulares en lugar de usar métodos de bajo nivel y tediosos en String y StringTokenizer.
Reemplazarfilter.java
paquete 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.servletRequest; javax.servlet.servletResponse; import javax.servlet.http.httpservletResponse; /*** Filtro que reemplaza todas las ocurrencias de una cadena dada con un* reemplazo. * Esta es una clase abstracta: usted <i> debe </i> anular los métodos de getTargetString* y getReplacementstring en una subclase.* El primero de estos métodos especifica la cadena en la respuesta* que debe reemplazarse. La segunda de estas especificaciones la cadena* que debe reemplazar cada ocurrencia de la cadena de destino. */clase public abstracta reemplazarfilter implementa filtro {private filterconfig config; Public void dofilter (solicitud de servletRequest, respuesta de servicio de servicio, cadena de filtro de filtro) lanza ServletException, ioexception {CharArrayWrapper Responsewrapper = new CharArrayWrapper ((httpServletResponse) respuesta); // Invocar el recurso, acumulando la salida en el envoltorio. Chain.dofilter (solicitud, RespuestaWrapper); // Convierte la salida completa en una cadena grande. String ResponseRing = ResponseWrapper.ToString (); // En la salida, reemplace todas las ocurrencias de la cadena de destino con reemplazo // cadena. ResponseString = FilterUtils.replace (ResponseRing, getTargetString (), getReplacementsTring ()); // Actualizar el encabezado de contenido. UpdateHeaders (respuesta, respuesta); PrintWriter out = Response.getWriter (); out.write (Response); } /*** Guarde el objeto FilterConfig en caso de que las subclases lo deseen. */ public void init (filterconfig config) lanza ServletException {this.config = config; } protegido FilterConfig getFilterConfig () {return (config); } public void destruye () {} /*** La cadena que necesita reemplazo.* Anule este método en su subclase. */ public Abstract String getTargetString (); /*** La cadena que reemplaza el objetivo. Anule este método en * su subclase. */ public abstract String getRePlacementsTring (); /*** Actualiza los encabezados de respuesta. Esta versión simple solo establece* el encabezado de longitud de contenido, suponiendo que estamos utilizando un conjunto de caracteres* que usa 1 byte por carácter.* Para otros conjuntos de caracteres, anule este método para usar* una lógica diferente o para renunciar a las conexiones HTTP persistentes.* En este último caso, haga que este método establezca el encabezado de conexión* a "cerrar". */ public void UpdateHeaders (Respuesta ServLetResponse, String ResponseString) {Response.SetContentLength (ResponseString.Length ()); }}
FilterUtils.java
paquete com.zj.sample; /*** Pequeña utilidad para ayudar con envoltorios de respuesta que devuelven cadenas. * /Public Class FilterUtils { /*** Cambie todas las ocurrencias de origen para reemplazar la creación de origen. */ public static String reemplazar (String Maintring, String Orig, Reemplazo de cadena) {String result = ""; int OldIndex = 0; int index = 0; int OrigLength = Orig.length (); while ((index = Mainstring.Indexof (orig, OldIndex))! = -1) {resultado = resultado + Mainstring.substring (OldIndex, índice) + reemplazo; OldIndex = index + OrigLength; } resultado = resultado + Mainstring.Substring (OldIndex); return (resultado); }} 7.3.2 Implemente un filtro de reemplazo de caracteres. Suponga que Baidu adquirió Google (solo una hipótesis), ¡todos los textos con la palabra Google en todas las páginas deben ser reemplazados por Baidu! ReplacesItenameFilter.java hereda el reemplazo de reemplazo.java anterior para implementar esta función. ReemplazareReNameFilter.javapackage com.zj.sample; Public Class ReplacesItEnameFilter extiende ReemplazarFilter {public String getTargetString () {return ("google.com.cn"); } public String getRepLacementsTring () {return ("baidu.com"); }}
web.xml
<filter> <filter-name>ReplaceSiteNameFilter</filter-name> <filter-class>com.zj.sample.ReplaceSiteNameFilter</filter-class></filter><filter-mapping> <filter-name>ReplaceSiteNameFilter</filter-name> <url-pattern>/login.jsp</url-pattern></filter-mapping>
Resultados de la prueba:
Antes de filtrar
Después de filtrar
8. Filtro de compresión
Hay varios navegadores más recientes que pueden manejar el contenido comprimido, desempaquetar automáticamente el archivo comprimido con GZIP como el valor del encabezado de respuesta de codificación de contenido y luego procesar los resultados al igual que el documento original. Enviar dicho contenido comprimido puede ahorrar mucho tiempo, porque el tiempo que lleva comprimir un documento en el servidor y luego deshacer el documento en el cliente es trivial en comparación con el tiempo que lleva descargar el archivo. El programa LongServlet.java ofrece un servlet con una salida de texto plana larga y duplicada, un servlet maduro para la compresión. Si usa GZIP, ¡puede comprimir la salida a 1/300!
Cuando el navegador admite esta capacidad de compresión, el filtro de compresión puede usar el CharArrayWrapper introducido en el Capítulo 7 para comprimir el contenido. Se requiere el siguiente contenido para completar esta tarea:
1) Clase que implementa la interfaz de filtro. Esta clase se llama CompressionFilter. El método Init almacena el objeto FilterConfig en un campo en caso de que la subclase necesite acceder al entorno de servlet o al nombre del filtro. El cuerpo del método Destory está vacío.
2) El objeto de respuesta envuelto. El método Dofilter envuelve el objeto ServLetResponse en un CharArrayWrapper y pasa este envoltorio al método Dofilter del objeto FilterChain. Después de completar esta llamada, se han ejecutado todos los demás filtros y recursos finales y la salida está dentro del envoltorio. De esta manera, el Dofilter original extrae una variedad de caracteres que representan el resultado de todos los recursos. Si el cliente establece que admite la compresión (es decir, tomar GZIP como un valor para el encabezado de codificación de aceptación), el filtro agrega un GZIPoutputStream al BytEarRayOutputStream, copie la matriz de caracteres en esta secuencia y establece el encabezado de respuesta de codificación de contenido a GZIP. Si el cliente no admite GZIP, copie la matriz de caracteres no modificada a ByTearRayOutputStream. Finalmente, Dofilter envía el resultado al cliente escribiendo toda la matriz de caracteres (probablemente comprimida) a la salida de salida asociada con la respuesta original.
3) Registre el Longservlet.
Compresionfilter.java
paquete com.zj.sample; import 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.servlet.filterchain; javax.servlet.filterConfig; import javax.servlet.servletException; import javax.servlet.servletRequest; import javax.servlet.servletResponse; import javax.servlet.http.httpservletRequest; import javax.servlet.http.htpservletResspersessessesponseSess. /** * Filtro que comprime la salida con GZIP (suponiendo que el navegador admite * GZIP). */Public Class CompressionFilter implementa Filter {private FilterConfig config; /*** Si el navegador no admite GZIP, invoca el recurso normalmente. Si el navegador * <i> </i> admite GZIP, configure el encabezado de respuesta de codificación de contenido y * invoca el recurso con una respuesta envuelta que recopila toda la salida. * Extraiga la salida y escríbela en una matriz de bytes gzipped. Finalmente, escriba * esa matriz a la secuencia de salida del cliente. */ public void dofilter (solicitud de servletRequest, respuesta de servicio de servicio, cadena de filtro de filtro) lanza ServletException, ioexception {httpservletRequest req = (httpservletRequest) solicitud; HttpservletResponse Res = (httpservletResponse) respuesta; if (! isgzipsupported (req)) {// Invoca el recurso normalmente. Chain.dofilter (req, res); } else {// Dígale al navegador que lo estamos enviando datos. res.setheader ("codificación de contenido", "gzip"); // Invocar el recurso, acumulando la salida en el envoltorio. CharArrayWrapper ResponseWrapper = new CharArrayWrapper (res); Chain.dofilter (Req, ResponseWrapper); // Obtener una matriz de caracteres que representa la salida. char [] Responsechars = ResponseWrapper.ToCarArray (); // Hacer un escritor que comprime datos y lo ponga en una matriz de bytes. ByteArRayOutputStream byTRESTREM = new byteArRaReOutputStream (); GzipoutputStream ZIPOut = new GzIPoutputStream (ByTRESTREAM); OutputStreamWriter tempout = new OutputStreamWriter (ZIPOUT); // comprimir la salida original y colóquela en la matriz de bytes. tempout.write (ResponseChars); // Las transmisiones GZIP deben cerrarse explícitamente. tempout.close (); // Actualizar el encabezado de contenido. res.setContentLength (bytreStream.size ()); // Enviar resultado comprimido al cliente. OutputStream RealOut = res.getOutputStream (); bytestream.writeTo (RealOut); }} /*** Almacene el objeto FilterConfig en caso de que las subclases lo deseen. */ public void init (filterconfig config) lanza ServletException {this.config = config; } protegido FilterConfig getFilterConfig () {return (config); } public void destruye () {} private booleano isgzipsupported (httpservletRequest req) {string browserEncodings = req.getheader ("aceptar-ending"); return ((browserEncodings! = null) && (browserEncodings.IndexOf ("gzip")! = -1)); }} LongServlet.javapackage com.zj.sample; import java.io.ioexception; import java.io.printwriter; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletRequest; import javax.servlet.http.httpservletResponse; /*** Servlet con <b> Long </b> Salida. Se utiliza para probar el efecto de la compresión * Filtro del Capítulo 9. */ Clase pública LongServlet extiende httpservlet {public void doget (httpservletRequest solicitud, httpservletreSponse respuesta) lanza ServletException, ioexception {Response.SetContentType ("Texto/ HTML"); PrintWriter out = Response.getWriter (); Cadena doctype = "<! DocType html public/"-// w3c // dtd html 4.0 " +" transitional // en/">/n"; Title de cadena = "Página larga"; out.println (DocType + "<html>/n" + "<head> <title>" + Title + "</title> </head>/n" + "<body bgcolor =/"#fdf5e6/">/n" + "<h1 align =/" center/">" + title + "</h1>/n"); Línea de cadena = "bla, bla, bla, bla, bla." + "Yadda, yadda, yadda, yadda"; para (int i = 0; i <10000; i ++) {out.println (línea); } out.println ("</body> </html>"); }}
web.xml
<Sterry> <Sterry-Name> CompressionFilter </filter-name> <filter-class> com.zj.sample.comPressionFilter </filter-class> </siltre> <filter-mapping> <filter-name> compresionFilter </filter-name> <ervlet-name-name> longservlet </servlet-name> </sille-mapping> <ervlet> <ervlet-name> Longservlet </Servlet> <Servlet-class> com.zj.sample.longservlet </servlet-class> </servlet> <ervlet-mapping> <ervlet-name> longservlet </servlet-name> <url-pattern>/longservlet </sul-Pattern> </servlet-mapping>