Uvod u Spring MVC HandlerInterceptor

1. Uvod

U ovom uputstvu usredotočit ćemo se na razumijevanje proljetnog MVC-a HandlerInterceptor i kako ga pravilno koristiti.

2. Proljetni MVC rukovatelj

Da bismo razumjeli presretača, vratimo se korak unatrag i pogledajmo HandlerMapping. Ovo preslikava metodu na URL, tako da DispatcherServlet moći će ga pozvati prilikom obrade zahtjeva.

I DispatcherServlet koristi HandlerAdapter da se zapravo prizove metoda.

Sad kad razumijemo cjelokupni kontekst - tu nailazi presretač rukovatelja. Koristit ćemo HandlerInterceptor za izvršavanje radnji prije rukovanja, nakon rukovanja ili nakon dovršenja (kada je prikaz izveden) zahtjeva.

Presretač se može koristiti za unakrsne probleme i za izbjegavanje ponavljajućih kodova rukovatelja poput bilježenja, promjene globalno korištenih parametara u Spring modelu itd.

U sljedećih nekoliko odjeljaka upravo ćemo to gledati - razlike između različitih implementacija presretača.

3. Ovisnosti Mavena

Da bi se koristila Presretači, morate uključiti sljedeći odjeljak u a ovisnosti odjeljak vašeg pom.xml datoteka:

 org.springframework spring-web 5.2.8.OBUSTAVLJANJE 

Najnoviju verziju možete pronaći ovdje.

4. Presretač opružnog rukovatelja

Presretači koji rade s HandlerMapping na okviru mora provoditi HandlerInterceptor sučelje.

Ovo sučelje sadrži tri glavne metode:

  • prehandle () - poziva se prije izvođenja stvarnog rukovatelja, ali pogled još nije generiran
  • postHandle () - poziva se nakon izvršenja obrađivača
  • afterCompletion () - poziva nakon završetka kompletnog zahtjeva i generiranja prikaza

Ove tri metode pružaju fleksibilnost u obavljanju svih vrsta prethodne i naknadne obrade.

I kratka napomena - glavna razlika između HandlerInterceptor i HandlerInterceptorAdapter je da u prvom moramo nadjačati sve tri metode: preHandle (), postHandle () i afterCompletion (), dok u drugom možemo primijeniti samo potrebne metode.

Kratka napomena prije nego što krenemo dalje - ako želite preskočiti teoriju i prijeći ravno na primjere, prijeđite točno u odjeljak 5.

Evo što jednostavno preHandle () implementacija će izgledati ovako:

@Override public boolean preHandle (HttpServletRequest zahtjev, HttpServletResponse odgovor, Object handler) baca Exception {// vaš kôd vraća true; }

Primijetite da metoda vraća a boolean vrijednost - koja Springu govori treba li obrađivač zahtjeva dalje obrađivati ​​(pravi) ili ne (lažno).

Dalje, imamo implementaciju postHandle ():

@Override public void postHandle (HttpServletRequest zahtjev, HttpServletResponse odgovor, rukovatelj objektima, ModelAndView modelAndView) baca izuzetak {// vaš kod}

Ova se metoda poziva odmah nakon obrade zahtjeva HandlerAdapter, ali prije generiranja pogleda.

I naravno, može se koristiti na mnogo načina - na primjer, u model možemo dodati avatar prijavljenog korisnika.

Konačna metoda koju moramo implementirati u običaj HandlerInterceptor provedba je afterCompletion ():

@Override public void afterCompletion (zahtjev za HttpServletRequest, odgovor HttpServletResponse, rukovatelj objektima, izuzetak ex) {// vaš kôd}

Kada se pogled uspješno generira, ovu udicu možemo koristiti za prikupljanje dodatnih statistika povezanih sa zahtjevom.

Posljednja napomena koju treba zapamtiti je da a HandlerInterceptor je registriran na DefaultAnnotationHandlerMapping grah, koji je odgovoran za primjenu presretača na bilo koju klasu označenu s @Controller bilješka. Štoviše, u svojoj web aplikaciji možete navesti bilo koji broj presretača.

5. Prilagođeni loger-presretač

U ovom ćemo se primjeru usredotočiti na prijavu u našu web aplikaciju. Prije svega, naš se razred treba proširiti HandlerInterceptorAdapter:

javna klasa LoggerInterceptor proširuje HandlerInterceptorAdapter {...}

Također moramo omogućiti prijavu u naš presretač:

privatni statički zapisnik dnevnika = LoggerFactory.getLogger (LoggerInterceptor.class);

To omogućuje Log4J da prikaže zapisnike, kao i da naznači koja klasa trenutno bilježi podatke na navedeni izlaz.

Dalje, usredotočimo se na implementacije prilagođenih presretača:

5.1. Metoda preHandle ()

Ova se metoda poziva prije obrade zahtjeva; vraća se pravi, kako bi se omogućilo da okvir dalje pošalje zahtjev metodi rukovatelja (ili sljedećem presretaču). Ako se metoda vrati lažno, Spring pretpostavlja da je zahtjev obrađen i nije potrebna daljnja obrada.

Kuku možemo koristiti za bilježenje podataka o parametrima zahtjeva: odakle zahtjev dolazi itd.

U našem primjeru bilježimo ove podatke pomoću jednostavnog loggera loggera:

@Override public boolean preHandle (HttpServletRequest zahtjev, HttpServletResponse response, Object handler) baca izuzetak {log.info ("[preHandle] [" + request + "]" + "[" + request.getMethod () + "]" + zahtjev .getRequestURI () + getParameters (zahtjev)); povratak istinit; } 

Kao što vidimo, bilježimo neke osnovne informacije o zahtjevu.

U slučaju da ovdje naletimo na lozinku, morat ćemo se pobrinuti da to ne prijavimo.

Jednostavna je mogućnost zamijeniti lozinke i bilo koju drugu osjetljivu vrstu podataka zvjezdicama.

Evo brze provedbe kako se to može učiniti:

privatni String getParameters (zahtjev HttpServletRequest) {StringBuffer objavljeno = novi StringBuffer (); Nabrajanje e = request.getParameterNames (); if (e! = null) {posted.append ("?"); } while (e.hasMoreElements ()) {if (posted.length ()> 1) {posted.append ("&"); } String curr = (Niz) e.nextElement (); posted.append (curr + "="); if (curr.contains ("lozinka") || curr.contains ("pass") || curr.contains ("pwd")) {posted.append ("*****"); } else {posted.append (request.getParameter (curr)); }} Niz ip = request.getHeader ("X-FORWARDED-FOR"); Niz ipAddr = (ip == null)? getRemoteAddr (zahtjev): ip; if (ipAddr! = null &&! ipAddr.equals ("")) {posted.append ("& _ psip =" + ipAddr); } povratak objavljen.toString (); }

Konačno, želimo dobiti izvornu IP adresu HTTP zahtjeva.

Evo jednostavne implementacije:

private String getRemoteAddr (HttpServletRequest zahtjev) {String ipFromHeader = request.getHeader ("X-FORWARDED-FOR"); if (ipFromHeader! = null && ipFromHeader.length ()> 0) {log.debug ("ip iz proxyja - X-FORWARDED-FOR:" + ipFromHeader); return ipFromHeader; } zahtjev za povratom.getRemoteAddr (); }

5.2. Metoda postHandle ()

Ova kuka radi kad HandlerAdapter se poziva rukovatelj, ali DispatcherServlet još nije prikazao pogled.

Ovu metodu možemo dodati za dodavanje dodatnih atributa ModelAndView ili za utvrđivanje vremena koje je rukovateljskom metodom potrebno za obradu zahtjeva klijenta.

U našem slučaju jednostavno prijavimo zahtjev neposredno prije DispatcherServlet će prikazati pogled.

@Override public void postHandle (zahtjev HttpServletRequest, odgovor HttpServletResponse, rukovatelj objektima, ModelAndView modelAndView) baca izuzetak {log.info ("[postHandle] [" + request + "]"); }

5.3. Metoda afterCompletion ()

Kada je zahtjev završen i prikaz je izveden, možemo dobiti podatke o zahtjevima i odgovorima, kao i informacije o iznimkama, ako je bilo takvih:

@Override javna praznina afterCompletion (zahtjev HttpServletRequest, odgovor HttpServletResponse, rukovatelj objektima, iznimka ex) baca iznimku {if (ex! = Null) {ex.printStackTrace (); } log.info ("[afterCompletion] [" + zahtjev + "] [iznimka:" + ex + "]"); }

6. Konfiguracija

Da bismo dodali naše presretače u konfiguraciju Spring, moramo nadjačati addInterceptors () metoda iznutra WebConfig razred koji provodi WebMvcConfigurer:

@Override public void addInterceptors (registar InterceptorRegistry) {registry.addInterceptor (novi LoggerInterceptor ()); }

Istu konfiguraciju možemo postići uređivanjem naše konfiguracijske datoteke XML Spring:

S ovom aktivnom konfiguracijom presretač će biti aktivan i svi zahtjevi u aplikaciji bit će pravilno evidentirani.

Napominjemo, ako je konfigurirano više presretača Spring, the preHandle () metoda izvršava se redoslijedom konfiguracije, dok postHandle () i afterCompletion () metode se pozivaju obrnutim redoslijedom.

Ako koristimo Spring Boot umjesto vanilla Spring, imajte na umu da ne komentiramo našu konfiguracijsku klasu s @EnableWebMvc, ili ćemo izgubiti na Bootovim automatskim konfiguracijama.

7. Zaključak

Ovaj je vodič kratki uvod u presretanje HTTP zahtjeva pomoću Spring MVC Handler Interceptor.

Svi primjeri i konfiguracije dostupni su ovdje na GitHubu.