Jar - Prihlásenie prichádzajúcich požiadaviek

1. Úvod

V tomto rýchlom výučbe si ukážeme základy protokolovania prichádzajúcich požiadaviek pomocou jarného filtra protokolovania. Ak s protokolovaním ešte len začínate, prečítajte si tento úvodný článok o protokolovaní, ako aj článok SLF4J.

2. Maven závislosti

Závislosti protokolovania budú jednoducho rovnaké ako tie v úvodnom článku; jednoducho sem pridajme jar:

 org.springframework spring-core 5.2.2.RELEASE 

Najnovšiu verziu nájdete tu pre spring-core.

3. Základný webový radič

Najskôr si definujeme radič, ktorý sa použije v našom príklade:

@RestController verejná trieda TaxiFareController {@GetMapping ("/ taxifare / get /") public RateCard getTaxiFare () {return new RateCard (); } @PostMapping ("/ taxifare / vypočítať /") verejný reťazec vypočítaťTaxiFare (@RequestBody @Valid TaxiRide taxiRide) {// vrátiť vypočítané cestovné}}

4. Vlastné zaznamenávanie požiadaviek

Jar poskytuje mechanizmus na konfiguráciu užívateľom definovaných zachytávačov na vykonávanie akcií pred a po webových požiadavkách.

Medzi zachytávačmi jarných požiadaviek je jedným z pozoruhodných rozhraní HandlerInterceptor, ktoré je možné použiť na prihlásenie prichádzajúcej žiadosti implementáciou nasledujúcich metód:

  1. preHandle () - táto metóda sa vykoná pred skutočnou metódou služby radiča
  2. po dokončení () - táto metóda sa vykoná potom, ako je radič pripravený na odoslanie odpovede

Okrem toho Spring poskytuje predvolenú implementáciu HandlerInterceptor rozhranie vo forme HandlerInterceptorAdaptor triedy, ktorú si môže užívateľ rozšíriť.

Vytvorme si vlastný zachytávač - predĺžením HandlerInterceptorAdaptor ako:

@Component public class TaxiFareRequestInterceptor extends HandlerInterceptorAdapter {@Override public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) {return true; } @Override public void afterCompletion (požiadavka HttpServletRequest, odpoveď HttpServletResponse, obsluha objektov, výnimka okrem) {//}}

Nakoniec nakonfigurujeme TaxiRideRequestInterceptor vo vnútri životného cyklu MVC na zachytenie predbežného a následného spracovania vyvolaných metód radiča, ktoré sú mapované na cestu / taxifare definované v TaxiFareController trieda.

@ Konfigurácia verejnej triedy TaxiFareMVCConfig implementuje WebMvcConfigurer {@Autowired private TaxiFareRequestInterceptor taxiFareRequestInterceptor; @Override public void addInterceptors (InterceptorRegistry registry) {registry.addInterceptor (taxiFareRequestInterceptor) .addPathPatterns ("/ ** / taxifare / ** /"); }}

Záverom je WebMvcConfigurer dodáva TaxiFareRequestInterceptor vo vnútri životného cyklu pružiny MVC vyvolaním addInterceptors () metóda.

Najväčšou výzvou je získať kópie užitočného zaťaženia žiadosti a odpovede na prihlásenie a stále nechať požadované užitočné zaťaženie pre jeho servlet.

Hlavným problémom žiadosti o čítanie je, že hneď ako sa vstupný prúd číta prvýkrát, je označený ako spotrebovaný a nedá sa znovu načítať.

Aplikácia po prečítaní streamu žiadosti vyvolá výnimku:

{"timestamp": 1500645243383, "status": 400, "error": "Bad Request", "exception": "org.springframework.http.converter .HttpMessageNotReadableException", "message": "Nemôžem prečítať dokument: Stream uzavretý ; vnorená výnimka je java.io.IOException: Stream closed "," path ":" / rest-log / taxifare / Calc / "}

Aby sme tento problém prekonali, môžeme využiť ukladanie do pamäte cache na uloženie streamu požiadaviek a jeho použitie na prihlásenie.

Jar poskytuje niekoľko užitočných tried, ako je ContentCachingRequestWrapper a ContentCachingResponseWrapper, ktoré je možné použiť na ukladanie údajov žiadosti do pamäte na účely protokolovania.

Prispôsobme si to preHandle () z TaxiRideRequestInterceptor triedy na uloženie objektu požiadavky do medzipamäte ContentCachingRequestWrapper trieda.

@Override public boolean preHandle (požiadavka HttpServletRequest, odpoveď HttpServletResponse, obsluha objektov) {HttpServletRequest requestCacheWrapperObject = nový ContentCachingRequestWrapper (požiadavka); requestCacheWrapperObject.getParameterMap (); // Načíta inputStream z requestCacheWrapperObject a prihlási ho späť true; }

Ako vidíme, uložili sme objekt žiadosti do pamäte cache ContentCachingRequestWrapper trieda, ktorá sa dá použiť na načítanie údajov užitočného zaťaženia na prihlásenie bez narušenia skutočného objektu požiadavky:

requestCacheWrapperObject.getContentAsByteArray ();

Obmedzenie

  • ContentCachingRequestWrapper trieda podporuje iba nasledujúce:
Typ obsahu: application / x-www-form-urlencoded Typ metódy: POST
  • Musíme vyvolať nasledujúcu metódu, aby sme sa ubezpečili, že údaje žiadosti sú uložené v pamäti ContentCachingRequestWrapper pred použitím:
requestCacheWrapperObject.getParameterMap ();

5. Jarné vstavané protokolovanie požiadaviek

Jar poskytuje vstavané riešenie na zaznamenávanie užitočného zaťaženia. Môžeme použiť hotové filtre pripojením do aplikácie Spring pomocou konfigurácie.

AbstractRequestLoggingFilter je filter, ktorý poskytuje základné funkcie protokolovania. Podtriedy by mali prepísať beforeRequest () a afterRequest () metódy na vykonanie skutočného prihlásenia okolo žiadosti.

Jarný rámec poskytuje tri konkrétne implementačné triedy, ktoré možno použiť na zaznamenávanie prichádzajúcich požiadaviek. Tieto tri triedy sú:

  • CommonsRequestLoggingFilter
  • Log4jNestedDiagnosticContextFilter (zastarané)
  • ServletContextRequestLoggingFilter

Teraz prejdime k CommonsRequestLoggingFilter a nakonfigurujte ho tak, aby zachytával prichádzajúce požiadavky na prihlásenie.

5.1. Nakonfigurujte aplikáciu Spring Boot

Aplikáciu Spring Boot je možné nakonfigurovať pridaním definície fazule, aby sa povolilo protokolovanie požiadaviek:

@Configuration verejná trieda RequestLoggingFilterConfig {@Bean public CommonsRequestLoggingFilter logFilter () {CommonsRequestLoggingFilter filter = nový CommonsRequestLoggingFilter (); filter.setIncludeQueryString (true); filter.setIncludePayload (true); filter.setMaxPayloadLength (10 000); filter.setIncludeHeaders (false); filter.setAfterMessagePrefix ("DOTAZNE DATA:"); spätný filter; }}

Tento filter protokolovania tiež vyžaduje, aby bola úroveň protokolu nastavená na DEBUG. Režim DEBUG môžeme povoliť pridaním prvku nižšie do logback.xml:

Ďalším spôsobom, ako povoliť protokol na úrovni DEBUG, je pridať nasledujúce položky do priečinka application.properties:

logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter = DEBUG

5.2. Konfigurácia tradičnej webovej aplikácie

V štandardnej webovej aplikácii Spring Filtrovať je možné nastaviť pomocou konfigurácie XML alebo konfigurácie Java. Poďme nastaviť CommonsRequestLoggingFilter pomocou konvenčnej konfigurácie založenej na prostredí Java.

Ako vieme, includePayload atribút CommonsRequestLoggingFilter je predvolene nastavená na hodnotu false. Potrebovali by sme vlastnú triedu, ktorá prepíše hodnotu povoleného atribútu includePayload pred injekciou do kontajnera pomocou konfigurácie Java:

public class CustomeRequestLoggingFilter rozširuje CommonsRequestLoggingFilter {public CustomeRequestLoggingFilter () {super.setIncludeQueryString (true); super.setIncludePayload (true); super.setMaxPayloadLength (10 000); }}

Teraz musíme podať injekciu CustomeRequestLoggingFilter pomocou webového inicializátora založeného na prostredí Java:

public class CustomWebAppInitializer implementuje WebApplicationInitializer {public void onStartup (ServletContext container) {AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext (); context.setConfigLocation ("com.baeldung"); container.addListener (nový ContextLoaderListener (kontext)); ServletRegistration.Dynamic dispečer = container.addServlet ("dispečer", nový DispatcherServlet (kontext)); dispatcher.setLoadOnStartup (1); dispatcher.addMapping ("/"); container.addFilter ("customRequestLoggingFilter", CustomeRequestLoggingFilter.class) .addMappingForServletNames (null, false, "dispečer"); }}

6. Príklad v akcii

Teraz môžeme zapojiť Spring Boot s kontextom a vidieť v akcii, že protokolovanie prichádzajúcich požiadaviek funguje podľa očakávania:

@Test public void givenRequest_whenFetchTaxiFareRateCard_thanOK () {TestRestTemplate testRestTemplate = nový TestRestTemplate (); TaxiRide taxiRide = nový TaxiRide (true, 10l); Reťazec cestovné = testRestTemplate.postForObject (URL + "vypočítať /", taxiRide, String.class); assertThat (cestovné, rovnaké ((200))); }

7. Záver

V tomto článku sme si ukázali, ako implementovať základné protokolovanie webových požiadaviek pomocou zachytávačov; ukázali sme tiež obmedzenia a výzvy tohto riešenia.

Potom sme si ukázali vstavanú triedu filtrov, ktorá poskytuje pripravený na použitie a jednoduchý mechanizmus protokolovania.

Implementácia príkladu a útržkov kódu sú ako vždy k dispozícii na serveri GitHub.


$config[zx-auto] not found$config[zx-overlay] not found