Inleiding tot Spring MVC HandlerInterceptor
1. Inleiding
In deze tutorial zullen we ons concentreren op het begrijpen van de Spring MVC HandlerInterceptor en hoe u het correct gebruikt. Laten we, om de interceptor te begrijpen, een stap terug doen en naar het HandlerMapping. Dit wijst een methode toe aan een URL, zodat de DispatcherServlet zal er een beroep op kunnen doen bij het verwerken van een verzoek. En de DispatcherServlet gebruikt de HandlerAdapter om de methode daadwerkelijk aan te roepen. Nu we de algemene context begrijpen - dit is waar de handler interceptor binnenkomt. We gebruiken de HandlerInterceptor om acties uit te voeren vóór afhandeling, na afhandeling of na voltooiing (wanneer de weergave wordt weergegeven) van een verzoek. De interceptor kan worden gebruikt voor transversale problemen en om repetitieve handlercodes zoals logboekregistratie, het wijzigen van wereldwijd gebruikte parameters in het Spring-model, enz. Te vermijden. In de volgende secties is dat precies waar we naar gaan kijken - de verschillen tussen verschillende interceptorimplementaties. Om te kunnen gebruiken Onderscheppers, moet u de volgende sectie opnemen in een afhankelijkheden sectie van uw pom.xml het dossier: De laatste versie vind je hier. Interceptors die werken met de HandlerMapping op het raamwerk moet de HandlerInterceptor koppel. Deze interface bevat drie hoofdmethoden: Deze drie methoden bieden flexibiliteit om allerlei soorten voor- en nabewerking uit te voeren. En een korte opmerking - het belangrijkste verschil tussen HandlerInterceptor en HandlerInterceptorAdapter is dat we in de eerste alle drie de methoden moeten negeren: preHandle (), postHandle () en na voltooiing(), terwijl we in de tweede alleen de vereiste methoden kunnen implementeren. Een korte opmerking voordat we verder gaan - als je de theorie wilt overslaan en direct naar voorbeelden wilt springen, ga dan direct naar sectie 5. Hier is wat een simpele preHandle () implementatie ziet er als volgt uit: Merk op dat de methode een boolean waarde - die Spring vertelt of het verzoek verder moet worden verwerkt door een handler (waar) of niet (false). Vervolgens hebben we een implementatie van postHandle (): Deze methode wordt onmiddellijk aangeroepen nadat het verzoek is verwerkt door HandlerAdapter, maar voordat een weergave wordt gegenereerd. En het kan natuurlijk op veel manieren worden gebruikt - we kunnen bijvoorbeeld een avatar van een ingelogde gebruiker aan een model toevoegen. De laatste methode die we moeten implementeren in de custom HandlerInterceptor implementatie is na voltooiing(): Als de weergave met succes is gegenereerd, kunnen we deze hook gebruiken om dingen te doen zoals het verzamelen van aanvullende statistieken met betrekking tot het verzoek. Een laatste opmerking om te onthouden is dat a HandlerInterceptor is geregistreerd bij de DefaultAnnotationHandlerMapping bean, die verantwoordelijk is voor het toepassen van interceptors op elke klasse gemarkeerd met een @Controller annotatie. Bovendien kunt u in uw webapplicatie een willekeurig aantal interceptors specificeren. In dit voorbeeld zullen we ons concentreren op het inloggen in onze webapplicatie. Allereerst moet onze klas worden uitgebreid HandlerInterceptorAdapter: We moeten ook inloggen op onze interceptor inschakelen: Dit stelt Log4J in staat om logs weer te geven, en om aan te geven welke klasse momenteel informatie registreert naar de opgegeven output. Laten we ons vervolgens concentreren op implementaties van aangepaste interceptor: Deze methode wordt aangeroepen voordat een verzoek wordt afgehandeld; het keert terug waar, om het raamwerk toe te staan het verzoek verder te sturen naar de afhandelingsmethode (of naar de volgende interceptor). Als de methode terugkeert false, Gaat Spring ervan uit dat het verzoek is afgehandeld en dat er geen verdere verwerking nodig is. We kunnen de hook gebruiken om informatie over de parameters van de verzoeken te loggen: waar het verzoek vandaan komt, enz. In ons voorbeeld loggen we deze informatie met behulp van een eenvoudige Log4J-logger: Zoals we kunnen zien, registreren we wat basisinformatie over het verzoek. Als we hier een wachtwoord tegenkomen, moeten we ervoor zorgen dat we dat natuurlijk niet loggen. Een eenvoudige optie is om wachtwoorden en elk ander gevoelig type gegevens te vervangen door sterren. Hier is een snelle implementatie van hoe dat kan worden gedaan: Ten slotte proberen we het bron-IP-adres van het HTTP-verzoek te krijgen. Hier is een eenvoudige implementatie: Deze haak loopt wanneer de HandlerAdapter wordt aangeroepen de handler maar DispatcherServlet moet de weergave nog weergeven. We kunnen deze methode gebruiken om extra attributen toe te voegen aan de ModelAndView of om de tijd te bepalen die de afhandelingsmethode nodig heeft om het verzoek van een cliënt te verwerken. In ons geval loggen we gewoon een verzoek net daarvoor in DispatcherServlet gaat een weergave maken. Wanneer een verzoek is voltooid en de weergave is weergegeven, kunnen we verzoek- en antwoordgegevens verkrijgen, evenals informatie over eventuele uitzonderingen: Om onze interceptors toe te voegen aan de Spring-configuratie, moeten we overschrijven addInterceptors () methode binnen Webconfiguratie klasse die implementeert WebMvcConfigurer: We kunnen dezelfde configuratie bereiken door ons XML Spring-configuratiebestand te bewerken: Als deze configuratie actief is, is de interceptor actief en worden alle verzoeken in de applicatie correct gelogd. Houd er rekening mee dat als er meerdere Spring-interceptors zijn geconfigureerd, de preHandle () methode wordt uitgevoerd in de volgorde van configuratie, terwijl postHandle () en na voltooiing() methoden worden in omgekeerde volgorde aangeroepen. Als we Spring Boot gebruiken in plaats van vanilla Spring, moeten we in gedachten houden om onze configuratieklasse niet te annoteren met @EnableWebMvc, of we verliezen de automatische configuraties van Boot. Deze tutorial is een korte inleiding tot het onderscheppen van HTTP-verzoeken met Spring MVC Handler Interceptor. Alle voorbeelden en configuraties zijn hier beschikbaar op GitHub.2. Veer MVC Handler
3. Maven afhankelijkheden
org.springframework spring-web 5.2.8.RELEASE
4. Spring Handler Interceptor
@Override public boolean preHandle (HttpServletRequest-verzoek, HttpServletResponse-antwoord, Object-handler) genereert Uitzondering {// uw code retourneert true; }
@Override public void postHandle (HttpServletRequest-verzoek, HttpServletResponse-antwoord, Objecthandler, ModelAndView modelAndView) genereert Uitzondering {// uw code}
@Override public void afterCompletion (HttpServletRequest-verzoek, HttpServletResponse-antwoord, Objecthandler, Exception ex) {// jouw code}
5. Aangepaste Logger Interceptor
openbare klasse LoggerInterceptor breidt HandlerInterceptorAdapter {...} uit
privé statisch logger-logboek = LoggerFactory.getLogger (LoggerInterceptor.class);
5.1. Methode preHandle ()
@Override public boolean preHandle (HttpServletRequest-verzoek, HttpServletResponse-antwoord, Objecthandler) genereert Uitzondering {log.info ("[preHandle] [" + request + "]" + "[" + request.getMethod () + "]" + verzoek .getRequestURI () + getParameters (verzoek)); terugkeer waar; }
private String getParameters (verzoek HttpServletRequest) {StringBuffer gepost = nieuwe StringBuffer (); Opsomming e = request.getParameterNames (); if (e! = null) {posted.append ("?"); } while (e.hasMoreElements ()) {if (posted.length ()> 1) {posted.append ("&"); } String curr = (String) e.nextElement (); posted.append (curr + "="); if (curr.contains ("wachtwoord") || curr.contains ("pass") || curr.contains ("pwd")) {posted.append ("*****"); } else {posted.append (request.getParameter (curr)); }} String ip = request.getHeader ("X-FORWARDED-FOR"); String ipAddr = (ip == null)? getRemoteAddr (verzoek): ip; if (ipAddr! = null &&! ipAddr.equals ("")) {posted.append ("& _ psip =" + ipAddr); } return posted.toString (); }
private String getRemoteAddr (verzoek HttpServletRequest) {String ipFromHeader = request.getHeader ("X-FORWARDED-FOR"); if (ipFromHeader! = null && ipFromHeader.length ()> 0) {log.debug ("ip van proxy - X-FORWARDED-FOR:" + ipFromHeader); retourneer ipFromHeader; } retourverzoek.getRemoteAddr (); }
5.2. Methode postHandle ()
@Override public void postHandle (HttpServletRequest-verzoek, HttpServletResponse-antwoord, Objecthandler, ModelAndView modelAndView) genereert Uitzondering {log.info ("[postHandle] [" + request + "]"); }
5.3. Methode na voltooiing()
@Override public void afterCompletion (HttpServletRequest-verzoek, HttpServletResponse-antwoord, Object-handler, Exception ex) genereert Uitzondering {if (ex! = Null) {ex.printStackTrace (); } log.info ("[afterCompletion] [" + request + "] [uitzondering:" + ex + "]"); }
6. Configuratie
@Override public void addInterceptors (InterceptorRegistry-register) {registry.addInterceptor (nieuwe LoggerInterceptor ()); }
7. Conclusie