Introduksjon til Spring MVC HandlerInterceptor
1. Introduksjon
I denne opplæringen vil vi fokusere på å forstå våren MVC HandlerInterceptor og hvordan du bruker den riktig. For å forstå interceptor, la oss ta et skritt tilbake og se på HandlerMapping. Dette tilordner en metode til en URL, slik at DispatcherServlet vil kunne påberope seg det når de behandler en forespørsel. Og DispatcherServlet bruker Handleradapter å faktisk påkalle metoden. Nå som vi forstår den generelle konteksten - det er her førerens avlyssner kommer inn. Vi bruker HandlerInterceptor å utføre handlinger før håndtering, etter håndtering eller etter fullføring (når visningen er gjengitt), av en forespørsel. Avskjæreren kan brukes til tverrgående bekymringer og for å unngå repeterende håndteringskode som logging, endring av globalt brukte parametere i vårmodell etc. I de neste par seksjonene er det akkurat det vi skal se på - forskjellene mellom forskjellige interceptor-implementeringer. For å bruke Avskjærere, må du ta med følgende avsnitt i a avhengigheter delen av din pom.xml fil: Den siste versjonen finner du her. Avskjærere som jobber med HandlerMapping på rammeverket må implementere HandlerInterceptor grensesnitt. Dette grensesnittet inneholder tre hovedmetoder: Disse tre metodene gir fleksibilitet til å gjøre alle slags for- og etterbehandling. Og et raskt notat - hovedforskjellen mellom HandlerInterceptor og HandlerInterceptorAdapter er at i den første må vi overstyre alle tre metodene: preHandle (), postHandle () og afterCompletion ()mens vi i det andre bare implementerer nødvendige metoder. Et raskt notat før vi går videre - hvis du vil hoppe over teorien og hoppe rett til eksempler, kan du hoppe rett inn i avsnitt 5. Her er det enkle preHandle () implementering vil se ut som: Legg merke til metoden returnerer a boolsk verdi - som forteller Spring om forespørselen skal behandles videre av en behandler (ekte) eller ikke (falsk). Deretter har vi en implementering av postHandle (): Denne metoden kalles umiddelbart etter at forespørselen er behandlet av Handleradapter, men før du genererer en visning. Og det kan selvfølgelig brukes på mange måter - for eksempel kan vi legge til en avatar til en pålogget bruker i en modell. Den siste metoden vi trenger å implementere i skikken HandlerInterceptor implementering er afterCompletion (): Når visningen er generert, kan vi bruke denne kroken til å gjøre ting som å samle inn ytterligere statistikk knyttet til forespørselen. En siste merknad å huske er at en HandlerInterceptor er registrert i StandardAnnotationHandlerMapping bean, som er ansvarlig for å bruke avlyttere på alle klasser som er merket med en @Kontrollør kommentar. Videre kan du spesifisere et hvilket som helst antall avlyttere i webapplikasjonen. I dette eksemplet vil vi fokusere på innlogging i webapplikasjonen. Først og fremst må klassen vår utvides HandlerInterceptorAdapter: Vi må også aktivere innlogging i interceptoren vår: Dette lar Log4J vise logger, samt indikere hvilken klasse som for øyeblikket logger informasjon til den angitte utgangen. La oss deretter fokusere på tilpassede interceptor-implementeringer: Denne metoden kalles før du behandler en forespørsel; det kommer tilbake ekte, for å la rammeverket sende forespørselen videre til behandlingsmetoden (eller til neste avlytter). Hvis metoden returnerer falsk, Spring forutsetter at forespørselen er behandlet og ingen videre behandling er nødvendig. Vi kan bruke kroken til å logge informasjon om forespørselens parametere: hvor forespørselen kommer fra, etc. I vårt eksempel logger vi denne informasjonen ved hjelp av en enkel Log4J-logger: Som vi ser, logger vi litt grunnleggende informasjon om forespørselen. I tilfelle vi får et passord her, må vi sørge for at vi ikke logger det selvfølgelig. Et enkelt alternativ er å erstatte passord og annen sensitiv type data med stjerner. Her er en rask implementering av hvordan det kan gjøres: Til slutt satser vi på å få kilden til IP-adressen til HTTP-forespørselen. Her er en enkel implementering: Denne kroken går når Handleradapter blir påkalt fører men DispatcherServlet er ennå ikke å gjengi utsikten. Vi kan bruke denne metoden for å legge til flere attributter til ModelAndView eller å bestemme tiden det tar med behandlermetoden å behandle en klients forespørsel. I vårt tilfelle logger vi bare en forespørsel like før DispatcherServlet kommer til å gjengi en visning. Når en forespørsel er ferdig og visningen er gjengitt, kan vi innhente forespørsels- og svardata, samt informasjon om unntak, hvis det skjedde: For å legge til interceptorene våre i vårkonfigurasjon, må vi overstyre addInterceptors () metode inni WebConfig klasse som implementerer WebMvcConfigurer: Vi kan oppnå den samme konfigurasjonen ved å redigere vår XML Spring-konfigurasjonsfil: Med denne konfigurasjonen aktiv vil avlytteren være aktiv, og alle forespørsler i applikasjonen vil bli riktig logget. Vær oppmerksom på at hvis flere fjæravskjærere er konfigurert, preHandle () metoden utføres i rekkefølgen av konfigurasjonen, mens postHandle () og afterCompletion () metoder påkalles i omvendt rekkefølge. Hvis vi bruker Spring Boot i stedet for vanilla Spring, bør vi huske å ikke kommentere konfigurasjonsklassen vår med @EnableWebMvc, ellers mister vi Boot-autokonfigurasjonene. Denne opplæringen er en rask introduksjon til avlytting av HTTP-forespørsler ved bruk av Spring MVC Handler Interceptor. Alle eksempler og konfigurasjoner er tilgjengelige her på GitHub.2. Vår MVC-håndterer
3. Maven-avhengigheter
org.springframework spring-web 5.2.8.RELEASE
4. Spring Handler Interceptor
@Override offentlig boolsk preHandle (HttpServletRequest-forespørsel, HttpServletResponse-svar, Objektbehandler) kaster Unntak {// koden din returnerer sann; }
@Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throw Exception {// your code}
@Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {// your code}
5. Custom Logger Interceptor
public class LoggerInterceptor utvider HandlerInterceptorAdapter {...}
privat statisk loggerlogg = LoggerFactory.getLogger (LoggerInterceptor.class);
5.1. Metode preHandle ()
@Override offentlig boolsk preHandle (HttpServletRequest-forespørsel, HttpServletResponse-svar, Objektbehandler) kaster unntak {log.info ("[preHandle] [" + request + "]" + "[" + request.getMethod () + "]" + forespørsel .getRequestURI () + getParameters (forespørsel)); returner sant; }
private String getParameters (HttpServletRequest request) {StringBuffer lagt ut = ny StringBuffer (); Oppregning e = request.getParameterNames (); hvis (e! = null) {posted.append ("?"); } mens (e.hasMoreElements ()) {if (posted.length ()> 1) {posted.append ("&"); } Streng curr = (String) e.nextElement (); lagt ut.append (curr + "="); hvis (curr.contains ("passord") || curr.contains ("pass") || curr.contains ("pwd")) {posted.append ("*****"); } annet {posted.append (request.getParameter (curr)); }} String ip = request.getHeader ("X-FORWARDED-FOR"); String ipAddr = (ip == null)? getRemoteAddr (forespørsel): ip; hvis (ipAddr! = null &&! ipAddr.equals ("")) {posted.append ("& _ psip =" + ipAddr); } retur postet.toString (); }
private String getRemoteAddr (HttpServletRequest request) {String ipFromHeader = request.getHeader ("X-FORWARDED-FOR"); hvis (ipFromHeader! = null && ipFromHeader.length ()> 0) {log.debug ("ip fra proxy - X-FORWARDED-FOR:" + ipFromHeader); return ipFromHeader; } returner forespørsel.getRemoteAddr (); }
5.2. Metode postHandle ()
@Override public void postHandle (HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) kaster Unntak {log.info ("[postHandle] [" + request + "]"); }
5.3. Metode afterCompletion ()
@Override public void afterCompletion (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) kaster Exception {if (ex! = Null) {ex.printStackTrace (); } log.info ("[afterCompletion] [" + forespørsel + "] [unntak:" + ex + "]"); }
6. Konfigurasjon
@Override public void addInterceptors (InterceptorRegistry registry) {registry.addInterceptor (new LoggerInterceptor ()); }
7. Konklusjon