Spring Interceptor werden verwendet, um Client-Anfragen abzufangen und zu verarbeiten. Manchmal möchten wir die HTTP-Anfrage abfangen und vor der Übergabe an die Controller-Handler-Methoden eine Verarbeitung durchführen. Hier kommen Spring MVC Interceptor ins Spiel.
Spring Interceptor
Genau wie wir Struts2 Interceptors haben, können wir unseren eigenen Spring Interceptor entweder durch Implementierung des Interface
org.springframework.web.servlet.HandlerInterceptor
oder durch Überschreiben der abstrakten Klasse org.springframework.web.servlet.handler.HandlerInterceptorAdapter
erstellen, die die Basimplementierung des HandlerInterceptor-Interfaces bereitstellt.
Spring Interceptor – HandlerInterceptor
Der Spring HandlerInterceptor deklariert drei Methoden, basierend darauf, wo wir die HTTP-Anfrage abfangen möchten.
- boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler): Diese Methode wird verwendet, um die Anfrage abzufangen, bevor sie an die Handler-Methode übergeben wird. Diese Methode sollte ‚true‘ zurückgeben, um Spring mitzuteilen, dass die Anfrage durch einen anderen Spring-Interceptor verarbeitet werden soll oder sie an die Handler-Methode gesendet werden soll, wenn keine weiteren Spring-Interceptoren vorhanden sind. Wenn diese Methode ‚false‘ zurückgibt, geht das Spring-Framework davon aus, dass die Anfrage vom Spring-Interceptor selbst behandelt wurde und keine weitere Verarbeitung erforderlich ist. In diesem Fall sollten wir das Antwortobjekt verwenden, um die Antwort an die Client-Anfrage zu senden. Das Objekt handler ist das ausgewählte Handler-Objekt zur Bearbeitung der Anfrage. Diese Methode kann auch eine Ausnahme auslösen, in diesem Fall sollte Spring MVC Exception Handling nützlich sein, um eine Fehlerseite als Antwort zu senden.
- void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView): Diese HandlerInterceptor-Interceptormethode wird aufgerufen, wenn der HandlerAdapter den Handler aufgerufen hat, aber DispatcherServlet die Ansicht noch nicht gerendert hat. Diese Methode kann verwendet werden, um zusätzliche Attribute zum ModelAndView-Objekt hinzuzufügen, die in den Ansichtsseiten verwendet werden sollen. Wir können diese Spring-Interceptor-Methode verwenden, um die vom Handler verwendete Zeit zur Verarbeitung der Client-Anfrage zu bestimmen.
- void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex): Dies ist eine HandlerInterceptor-Rückrufmethode, die aufgerufen wird, sobald der Handler ausgeführt und die Ansicht gerendert wurde.
Wenn mehrere Spring-Interceptor konfiguriert sind, wird die preHandle()-Methode in der Konfigurationsreihenfolge ausgeführt, während die postHandle()– und afterCompletion()-Methoden in umgekehrter Reihenfolge aufgerufen werden. Lassen Sie uns eine einfache Spring-MVC-Anwendung erstellen, in der wir einen Spring-Interceptor konfigurieren, um die Zeitabläufe der Controller-Handlermethode zu protokollieren. Unser endgültiges Beispielprojekt für Spring Interceptor wird wie das untenstehende Bild aussehen. Wir werden uns die Komponenten ansehen, für die wir interessiert sind.
Spring Interceptor – Controller-Klasse
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.
*/
@Controller
public 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);
// Fügen Sie eine Zeitverzögerung hinzu, um die Ausführung des Interceptors zu überprüfen
try {
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";
}
}
I am just adding some processing time in the execution of the handler method to check our spring interceptor methods in action.
Spring MVC Interceptor – HandlerInterceptorAdapter Implementierung
Für die Einfachheit erweitere ich die abstrakte Klasse HandlerInterceptorAdapter
. HandlerInterceptorAdapter ist eine abstrakte Adapterklasse für das HandlerInterceptor-Interface, um eine vereinfachte Implementierung von Vor- oder Nachinterzeptoren zu ermöglichen.
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);
@Override
public 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);
// Wenn false zurückgegeben wird, müssen wir sicherstellen, dass 'response' gesendet wird
return true;
}
@Override
public 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());
// Wir können Attribute im modelAndView hinzufügen und diese in der Ansichtsseite verwenden
}
@Override
public 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));
}
}
Die Logik ist wirklich einfach. Ich protokolliere nur die Zeiten der Ausführung der Handlermethode und die Gesamtzeit, die für die Verarbeitung der Anforderung einschließlich des Renderns der Ansichtsseite benötigt wird.
Spring MVC Interceptor-Konfiguration
Wir müssen den Spring Interceptor an die Anfragen binden. Wir können das Element mvc:interceptors verwenden, um alle Interzeptoren zu verbinden. Wir können auch ein URI-Muster bereitstellen, um vor dem Einbeziehen des Spring Interceptors für die Anforderung abzugleichen, indem wir das Element mapping verwenden. Unsere endgültige Spring-Bean-Konfigurationsdatei (spring.xml) sieht folgendermaßen aus.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
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.xsd
https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://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:bean
class="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 -->
<interceptors>
<interceptor>
<mapping path="/home" />
<beans:bean class="com.journaldev.spring.RequestProcessingTimeInterceptor"></beans:bean>
</interceptor>
</interceptors>
<context:component-scan base-package="com.journaldev.spring" />
</beans:beans>
I will not explain all other components of the web application, because we are not interested in them and they don’t have any specific spring interceptor related configuration.
Spring MVC Interceptor-Anwendungstest
Deployen Sie einfach die Anwendung im Servlet-Container und rufen Sie den HomeController auf. Sie werden eine Protokollausgabe sehen, die ungefähr so aussieht.
INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: Start Time=1396906442086
INFO : com.journaldev.spring.HomeController - Welcome home! The client locale is en_US.
INFO : com.journaldev.spring.HomeController - Before returning view page
Request URL::https://localhost:9090/SpringInterceptors/home Sent to Handler :: Current Time=1396906443098
INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: End Time=1396906443171
INFO : com.journaldev.spring.RequestProcessingTimeInterceptor - Request URL::https://localhost:9090/SpringInterceptors/home:: Time Taken=1085
Die Ausgabe bestätigt, dass die Spring-Interceptor-Methoden in der definierten Reihenfolge ausgeführt werden. Das ist alles für die Verwendung von Spring-Interceptors. Sie können das Spring Interceptor Beispielprojekt über den untenstehenden Link herunterladen und versuchen, mehrere Interceptors zu haben und durch unterschiedliche Konfigurationsreihenfolgen zu überprüfen.