Introduktion til Spring MVC HandlerInterceptor

1. Introduktion

I denne vejledning fokuserer vi på at forstå Spring MVC HandlerInterceptor og hvordan man bruger det korrekt.

2. Fjeder MVC-håndterer

For at forstå interceptor, lad os tage et skridt tilbage og se på HandlerMapping. Dette kortlægger en metode til en URL, således at DispatcherServlet vil være i stand til at påberåbe sig det, når man behandler en anmodning.

Og DispatcherServlet bruger Handler-adapter for faktisk at påberåbe sig metoden.

Nu hvor vi forstår den overordnede kontekst - det er her, der handler interceptor kommer ind. Vi bruger HandlerInterceptor at udføre handlinger inden håndtering, efter håndtering eller efter afslutning (når visningen gengives) af en anmodning.

Interceptoren kan bruges til tværgående bekymringer og for at undgå gentagne handlingskoder som logning, ændring af globalt anvendte parametre i Spring-model osv.

I de næste par sektioner er det præcis, hvad vi skal se på - forskellene mellem forskellige interceptorimplementeringer.

3. Maven-afhængigheder

For at bruge Opfangere, skal du medtage følgende afsnit i a afhængigheder sektion af din pom.xml fil:

 org.springframework spring-web 5.2.8.RELEASE 

Den seneste version kan findes her.

4. Spring Handler Interceptor

Opfangere, der arbejder med HandlerMapping på rammen skal gennemføre HandlerInterceptor interface.

Denne grænseflade indeholder tre hovedmetoder:

  • forhandle () - kaldes før den faktiske handler udføres, men visningen er ikke genereret endnu
  • postHandle () - kaldes efter at handleren er henrettet
  • afterCompletion () - kaldes op efter den komplette anmodning er færdig og visningen blev genereret

Disse tre metoder giver fleksibilitet til at udføre alle former for for- og efterbehandling.

Og en hurtig note - den største forskel mellem HandlerInterceptor og HandlerInterceptorAdapter er, at i den første skal vi tilsidesætte alle tre metoder: preHandle (), postHandle () og afterCompletion (), mens vi i det andet kun implementerer nødvendige metoder.

En hurtig note, inden vi går videre - hvis du vil springe over teorien og springe direkte til eksempler, skal du hoppe lige ind i afsnit 5.

Her er hvad en simpel preHandle () implementering vil se ud:

@Override offentlig boolsk preHandle (HttpServletRequest anmodning, HttpServletResponse svar, Objektbehandler) kaster Undtagelse {// din kode returnerer sand; }

Bemærk, at metoden returnerer a boolsk værdi - som fortæller Spring, om anmodningen skal behandles yderligere af en handler (rigtigt) eller ikke (falsk).

Dernæst har vi en implementering af postHandle ():

@Override public void postHandle (HttpServletRequest anmodning, HttpServletResponse svar, Objektbehandler, ModelAndView modelAndView) kaster Undtagelse {// din kode}

Denne metode kaldes straks efter anmodningen er behandlet af Handler-adapter, men inden du genererer en visning.

Og det kan selvfølgelig bruges på mange måder - for eksempel kan vi tilføje en avatar fra en logget bruger i en model.

Den sidste metode, vi skal implementere i skikken HandlerInterceptor implementering er afterCompletion ():

@Override public void afterCompletion (HttpServletRequest anmodning, HttpServletResponse svar, Objektbehandler, Undtagelse ex) {// din kode}

Når visningen er genereret, kan vi bruge denne krog til at gøre ting som at indsamle yderligere statistik relateret til anmodningen.

En sidste note at huske er, at en HandlerInterceptor er registreret til StandardAnnotationHandlerMapping bean, som er ansvarlig for at anvende interceptors på enhver klasse markeret med a @Kontrol kommentar. Desuden kan du angive et hvilket som helst antal interceptors i din webapplikation.

5. Custom Logger Interceptor

I dette eksempel vil vi fokusere på logning i vores webapplikation. Først og fremmest skal vores klasse udvides HandlerInterceptorAdapter:

public class LoggerInterceptor udvider HandlerInterceptorAdapter {...}

Vi skal også aktivere logning i vores interceptor:

privat statisk loggerlog = LoggerFactory.getLogger (LoggerInterceptor.class);

Dette gør det muligt for Log4J at vise logfiler samt angive, hvilken klasse der i øjeblikket logger information til den specificerede output.

Lad os derefter fokusere på tilpassede interceptorimplementeringer:

5.1. Metode preHandle ()

Denne metode kaldes inden behandling af en anmodning; det vender tilbage rigtigt, at tillade rammen at sende anmodningen videre til behandlingsmetoden (eller til den næste interceptor). Hvis metoden vender tilbage falskSpring antager, at anmodningen er blevet håndteret, og der er ikke behov for yderligere behandling.

Vi kan bruge krogen til at logge information om anmodningernes parametre: hvor anmodningen kommer fra osv.

I vores eksempel logger vi denne info ved hjælp af en simpel Log4J-logger:

@Override offentlig boolsk preHandle (HttpServletRequest anmodning, HttpServletResponse svar, Objektbehandler) kaster undtagelse {log.info ("[preHandle] [" + anmodning + "]" + "[" + request.getMethod () + "]" + anmodning .getRequestURI () + getParameters (anmodning)); returner sandt; } 

Som vi kan se, logger vi nogle grundlæggende oplysninger om anmodningen.

I tilfælde af at vi løber ind i en adgangskode her, skal vi selvfølgelig ikke logge det.

En enkel mulighed er at erstatte adgangskoder og enhver anden følsom type data med stjerner.

Her er en hurtig implementering af, hvordan det kan gøres:

private String getParameters (HttpServletRequest anmodning) {StringBuffer sendt = ny StringBuffer (); Optælling e = request.getParameterNames (); hvis (e! = null) {posted.append ("?"); } mens (e.hasMoreElements ()) {if (posted.length ()> 1) {posted.append ("&"); } String curr = (String) e.nextElement (); posted.append (curr + "="); hvis (curr.contains ("password") || curr.contains ("pass") || curr.contains ("pwd")) {posted.append ("*****"); } andet {posted.append (request.getParameter (curr)); }} String ip = request.getHeader ("X-FORWARDED-FOR"); String ipAddr = (ip == null)? getRemoteAddr (anmodning): ip; hvis (ipAddr! = null &&! ipAddr.equals ("")) {posted.append ("& _ psip =" + ipAddr); } returneret. toString (); }

Endelig sigter vi mod at få kilde-IP-adressen til HTTP-anmodningen.

Her er en simpel implementering:

private String getRemoteAddr (HttpServletRequest anmodning) {String ipFromHeader = request.getHeader ("X-FORWARDED-FOR"); hvis (ipFromHeader! = null && ipFromHeader.length ()> 0) {log.debug ("ip fra proxy - X-FORWARDED-FOR:" + ipFromHeader); returner ipFromHeader; } returner anmodning.getRemoteAddr (); }

5.2. Metode postHandle ()

Denne krog kører, når Handler-adapter påberåbes handler men DispatcherServlet er endnu ikke til at gengive udsigten.

Vi kan bruge denne metode til at tilføje yderligere attributter til ModelAndView eller at bestemme, hvor lang tid det tager med behandlingsmetoden at behandle en klients anmodning.

I vores tilfælde logger vi simpelthen en anmodning lige før DispatcherServlet kommer til at gengive en visning.

@ Overstyr offentlig ugyldig postHandle (HttpServletRequest anmodning, HttpServletResponse svar, Objektbehandler, ModelAndView modelAndView) kaster Undtagelse {log.info ("[postHandle] [" + anmodning + "]"); }

5.3. Metode afterCompletion ()

Når en anmodning er færdig, og visningen gengives, kan vi indhente anmodnings- og svardata samt oplysninger om undtagelser, hvis der opstod:

@Override public void afterCompletion (HttpServletRequest anmodning, HttpServletResponse svar, Objektbehandler, Exception ex) kaster Exception {if (ex! = Null) {ex.printStackTrace (); } log.info ("[afterCompletion] [" + anmodning + "] [undtagelse:" + ex + "]"); }

6. Konfiguration

For at tilføje vores interceptors i Spring-konfiguration er vi nødt til at tilsidesætte addInterceptors () metode indeni WebConfig klasse, der implementerer WebMvcConfigurer:

@Override offentlige ugyldige addInterceptors (InterceptorRegistry registry) {registry.addInterceptor (ny LoggerInterceptor ()); }

Vi opnår muligvis den samme konfiguration ved at redigere vores XML Spring-konfigurationsfil:

Når denne konfiguration er aktiv, vil interceptoren være aktiv, og alle anmodninger i applikationen vil blive logget korrekt.

Bemærk, at hvis der er konfigureret flere fjederinterceptorer, skal preHandle () metoden udføres i rækkefølgen af ​​konfigurationen, mens postHandle () og afterCompletion () metoder påberåbes i omvendt rækkefølge.

Hvis vi bruger Spring Boot i stedet for vanilla Spring, skal vi huske på ikke at kommentere vores konfigurationsklasse med @EnableWebMvc, ellers mister vi Boot's automatiske konfigurationer.

7. Konklusion

Denne vejledning er en hurtig introduktion til at opfange HTTP-anmodninger ved hjælp af Spring MVC Handler Interceptor.

Alle eksempler og konfigurationer er tilgængelige her på GitHub.