Filtros e interceptores
Filtros e interceptores son objetos que pueden ser utilizados en el procesamiento de solicitudes o respuestas del servidor.
Estos objetos permiten encapsular comportamiento relacionado con el procesamiento de aspectos del protocolo o infraestructura de la aplicación y que no deseamos manejar en el modelo de negocios.
Los filtros e interceptores pueden ser utilizados tanto del lado del cliente como del lado del servidor.
Filtros
Los filtros pueden modificar solicitudes y respuestas al servidor, incluyendo los headers y otros parametros de request/response.
Interceptores
Los interceptores son utilizados para modificar el contenido del mensaje, tanto de entrada como de salida. Por ejemplo comprimir y descomprimir o encriptar y desencriptar mensajes.
Configuración del orden de ejecución de filtros e interceptores
Si tenemos más de un filtro o interceptor, debemos definir el orden en el que deseamos que se ejecuten. En JAX-RS el orden de ejecución se puede fijar por medio de la anotación @Priority y en tiempo de ejecución el orden será determinado por medio del valor asignado, ejecutando primero los números más pequeños.
Si no se configura, los filtros e interceptores aplican a todas las solicitudes y respuestas del servidor, sin embargo se puede aplicar a métodos de recursos seleccionados por medio del registro de una implementación de la interfaz DinamicFeature o por medio de anotaciones. Para más información consultar la sección dynamic binding y name binding de la página oficial de Jersey.
Descomprimir/Comprimir solicitudes y respuestas del servidor
Vamos a crear un interceptor para comprimir y descomprimir los mensajes
Primero veremos como descomprimir el contenido del mensaje, para que cuando se ejecute el recurso deseado, los datos vayan en su formato no comprimido. Vamos a crear la clase CompresionReaderInterceptor con el siguiente código:
@Provider public class CompresionReaderInterceptor implements ReaderInterceptor { @Override public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException { String encoding = context.getHeaders().getFirst(CompresionWriterInterceptor.CONTENT_ENCODING_HEADER); if (!requestHasContentEncodingHeader(encoding)) { return context.proceed(); } GZIPInputStream gzipInputStream = new GZIPInputStream(context.getInputStream()); context.setInputStream(gzipInputStream); return context.proceed(); } private boolean requestHasContentEncodingHeader(String encoding) { return CompresionWriterInterceptor.CONTENT_ENCODING_HEADER_VALUE .equalsIgnoreCase(encoding); } }
Ahora vamos a crear la clase CompresionWriterInterceptor para comprimir el contenido del mensaje una vez que se ha procesado el recurso solicitado.
@Provider public class CompresionWriterInterceptor implements WriterInterceptor { public static final String CONTENT_ENCODING_HEADER_VALUE = "gzip"; public static final String CONTENT_ENCODING_HEADER = "Content-Encoding"; @Override public void aroundWriteTo(WriterInterceptorContext context) throws IOException, WebApplicationException { GZIPOutputStream gzipOuputStream = new GZIPOutputStream( context.getOutputStream()); context.getHeaders().putSingle(CONTENT_ENCODING_HEADER, CONTENT_ENCODING_HEADER_VALUE); context.setOutputStream(gzipOuputStream); context.proceed(); return; } }
La anotación @Provider es la que permite que se detecte la clase como un elemento de interés para el servicio. Esta clase también puede ser registrada en la implementación de Application.
Aplicando filtros por medio de anotaciones
Como se mencionó antes si no se configura, los filtros e interceptores aplican a todos los request y responses del servicio. Vamos a ver como aplicarlo a solo un método de un recurso.
Necesitamos crear la siguiente anotación:
import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import javax.ws.rs.NameBinding; /** * Permite especificar los recursos a los que se requiere aplicar un algoritmo * para comprimir y descomprimir mensajes. * * @author Clemente Morales Fernández * @since Oct 30, 2014 * */ @NameBinding @Retention(RetentionPolicy.RUNTIME) public @interface Compress { }
Una vez creada la anotación lo que haremos será aplicarla en el método del recurso que deseamos aplicar compresión en la respuesta y al interceptor encargado de realizar la compresión.
@Compress public class CompresionWriterInterceptor implements WriterInterceptor { } /** * Proporciona las operaciones disponibles para el recurso seguro. * * @author Clemente Morales Fernández * */ @Path("seguros") public interface SegurosService { /** * Permite obtener los seguros dados de alta por un cliente. * @param idCliente Identificador del cliente. * @return Lista de seguros del cliente. */ @Path("/{idCliente}") @GET @Produces("application/json") @Compress ListgetSegurosCliente(@PathParam("idCliente") int idCliente); }
En la siguiente entrada veremos como crear y configurar filtros e interceptores del lado del cliente.
No hay comentarios:
Publicar un comentario