Ejemplo de HandlerInterceptorAdapter, HandlerInterceptor de Spring MVC

Spring Interceptor se utiliza para interceptar solicitudes de clientes y procesarlas. A veces, queremos interceptar la solicitud HTTP y realizar algún procesamiento antes de entregársela a los métodos de manejo del controlador. Ahí es donde Spring MVC Interceptor resulta útil.

Interceptor de primavera

Al igual que tenemos los interceptores Struts2 , podemos crear nuestro propio interceptor Spring implementando org.springframework.web.servlet.HandlerInterceptorla interfaz o anulando la clase abstracta org.springframework.web.servlet.handler.HandlerInterceptorAdapterque proporciona la implementación base de la interfaz HandlerInterceptor.

Interceptor de resorte – HandlerInterceptor

Spring HandlerInterceptor declara tres métodos según dónde queramos interceptar la solicitud HTTP.

  1. boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) : Este método se utiliza para interceptar la solicitud antes de que se entregue al método controlador. Este método debe devolver ‘true’ para que Spring sepa que debe procesar la solicitud a través de otro interceptor de Spring o enviarla al método controlador si no hay más interceptores de Spring. Si este método devuelve ‘false’, el marco de Spring asume que la solicitud ha sido manejada por el propio interceptor de Spring y no se necesita ningún procesamiento adicional. Deberíamos usar el objeto de respuesta para enviar la respuesta a la solicitud del cliente en este caso. El objeto controlador es el objeto controlador elegido para manejar la solicitud. Este método también puede lanzar una excepción, en ese caso, el manejo de excepciones de Spring MVC debería ser útil para enviar una página de error como respuesta.
  2. void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) : Este método interceptor HandlerInterceptor se llama cuando HandlerAdapter ha invocado el controlador pero DispatcherServlet aún debe representar la vista. Este método se puede utilizar para agregar atributos adicionales al objeto ModelAndView que se utilizarán en las páginas de vista. Podemos utilizar este método interceptor de Spring para determinar el tiempo que tarda el método del controlador en procesar la solicitud del cliente.
  3. void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) : este es un método de devolución de llamada HandlerInterceptor que se llama una vez que se ejecuta el controlador y se representa la vista.

Si hay varios interceptores de resorte configurados, el método preHandle() se ejecuta en el orden de configuración, mientras que los métodos postHandle() y afterCompletion() se invocan en el orden inverso. Creemos una aplicación Spring MVC simple en la que configuraremos un interceptor de resorte para registrar los tiempos del método del controlador. Nuestro proyecto de ejemplo final de Spring Interceptor se verá como la imagen de abajo, analizaremos los componentes que nos interesan.

Interceptor de resorte: clase controladora

package com.journaldev.spring;import java.text.DateFormat;import java.util.Date;import java.util.Locale;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;/** * Handles requests for the application home page. */@Controllerpublic class HomeController {private static final Logger logger = LoggerFactory.getLogger(HomeController.class);@RequestMapping(value = "/home", method = RequestMethod.GET)public String home(Locale locale, Model model) {logger.info("Welcome home! The client locale is {}.", locale);//adding some time lag to check interceptor executiontry {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}Date date = new Date();DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);String formattedDate = dateFormat.format(date);model.addAttribute("serverTime", formattedDate );logger.info("Before returning view page");return "home";}}

Simplemente estoy agregando algo de tiempo de procesamiento en la ejecución del método del controlador para verificar nuestros métodos de interceptor de resorte en acción.

Implementación de HandlerInterceptorAdapter de Spring MVC Interceptor

Para simplificar, estoy ampliando la clase abstracta HandlerInterceptorAdapterHandlerInterceptorAdapter. Esta es una clase de adaptador abstracto para la interfaz HandlerInterceptor, para una implementación simplificada de interceptores de solo pre/solo post.

package com.journaldev.spring;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;public class RequestProcessingTimeInterceptor extends HandlerInterceptorAdapter {private static final Logger logger = LoggerFactory.getLogger(RequestProcessingTimeInterceptor.class);@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {long startTime = System.currentTimeMillis();logger.info("Request URL::" + request.getRequestURL().toString()+ ":: Start Time=" + System.currentTimeMillis());request.setAttribute("startTime", startTime);//if returned false, we need to make sure 'response' is sentreturn true;}@Overridepublic void postHandle(HttpServletRequest request,HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {System.out.println("Request URL::" + request.getRequestURL().toString()+ " Sent to Handler :: Current Time=" + System.currentTimeMillis());//we can add attributes in the modelAndView and use that in the view page}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response, Object handler, Exception ex)throws Exception {long startTime = (Long) request.getAttribute("startTime");logger.info("Request URL::" + request.getRequestURL().toString()+ ":: End Time=" + System.currentTimeMillis());logger.info("Request URL::" + request.getRequestURL().toString()+ ":: Time Taken=" + (System.currentTimeMillis() - startTime));}}

La lógica es realmente simple, solo estoy registrando los tiempos de ejecución del método del controlador y el tiempo total necesario para procesar la solicitud, incluida la representación de la página de vista.

Configuración del interceptor Spring MVC

Tenemos que conectar el interceptor Spring a las solicitudes. Podemos usar el elemento mvc:interceptors para conectar todos los interceptores. También podemos proporcionar un patrón de URI para que coincida antes de incluir el interceptor Spring para la solicitud a través del elemento de mapeo . Nuestro archivo de configuración final de Spring Bean (spring.xml) se ve como se muestra a continuación.

?xml version="1.0" encoding="UTF-8"?beans:beans xmlns_xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns_beans="https://www.springframework.org/schema/beans"xmlns:context="https://www.springframework.org/schema/context"xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsdhttps://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsdhttps://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure --!-- Enables the Spring MVC @Controller programming model --annotation-driven /!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory --resources mapping="/resources/**" location="/resources/" /!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory --beans:beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"beans:property name="prefix" value="/WEB-INF/views/" /beans:property name="suffix" value=".jsp" //beans:bean!-- Configuring interceptors based on URI --interceptorsinterceptormapping path="/home" /beans:bean/beans:bean/interceptor/interceptorscontext:component-scan base-package="com.journaldev.spring" //beans:beans

No explicaré todos los demás componentes de la aplicación web, porque no nos interesan y no tienen ninguna configuración específica relacionada con el interceptor de resorte.

Pruebas de aplicaciones de Spring MVC Interceptor

Simplemente implemente la aplicación en el contenedor de servlets e invoque el controlador de inicio; verá un resultado del registrador similar a lo que se muestra a continuación.

INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: Start Time=1396906442086INFO : com.journaldev.spring.HomeController - Welcome home! The client locale is en_US.INFO : com.journaldev.spring.HomeController - Before returning view pageRequest URL::https://localhost:9090/SpringInterceptors/home Sent to Handler :: Current Time=1396906443098INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: End Time=1396906443171INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: Time Taken=1085

La salida confirma que los métodos del interceptor de resorte se ejecutan en el orden definido. Eso es todo acerca del uso de los interceptores de resorte. Puede descargar el proyecto de ejemplo de interceptor de resorte desde el siguiente enlace e intentar tener varios interceptores y verificarlos en diferentes órdenes de configuración.

Descargar Proyecto Spring Interceptors

SUSCRÍBETE A NUESTRO BOLETÍN 
No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio