Tavasz - Bejövő kérések naplózása
1. Bemutatkozás
Ebben a gyors bemutatóban bemutatjuk a bejövő kérések naplózásának alapjait a Spring naplózási szűrője segítségével. Ha még csak most kezdi a naplózást, olvassa el ezt a naplózási bevezető cikket, valamint az SLF4J cikket.
2. Maven-függőségek
A naplózási függőségek egyszerűen megegyeznek az intro cikkben szereplőkkel; tegyük egyszerűen ide a Tavaszt:
org.springframework rugós mag 5.2.2.FELHASZNÁLÁS
A legfrissebb verzió itt található a rugós maghoz.
3. Alapvető webvezérlő
Először is definiáljunk egy vezérlőt, amelyet a példánkban használunk:
@RestController public class TaxiFareController {@GetMapping ("/ taxifare / get /") public RateCard getTaxiFare () {return new RateCard (); } @PostMapping ("/ taxifare / calc /") public String calcTaxiFare (@RequestBody @Valid TaxiRide taxiRide) {// adja vissza a kiszámított viteldíjat}}
4. Egyedi kérelem naplózása
A Spring mechanizmust biztosít a felhasználó által meghatározott elfogók konfigurálására a webes kérések előtti és utáni műveletek végrehajtására.
A tavaszi kérést elfogók között az egyik figyelemre méltó felület a HandlerInterceptor, amely a bejövő kérelem naplózására használható a következő módszerek végrehajtásával:
- preHandle () - ezt a módszert a tényleges vezérlőszolgáltatási módszer előtt hajtják végre
- afterCompletion () - ezt a módszert akkor hajtják végre, miután a vezérlő készen áll a válasz küldésére
Ezenkívül a Spring biztosítja a HandlerInterceptor interfész formájában HandlerInterceptorAdaptor osztály, amelyet a felhasználó kibővíthet.
Hozzunk létre saját elfogót - kiterjesztéssel HandlerInterceptorAdaptor mint:
A @Component public class TaxiFareRequestInterceptor kiterjeszti a HandlerInterceptorAdaptert {@Orride public boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handler) {return true; } @Orride public void afterCompletion (HttpServletRequest kérés, HttpServletResponse válasz, Objektumkezelő, Kivétel ex) {//}}
Végül konfiguráljuk a TaxiRideRequestInterceptor az MVC életciklusán belül, hogy rögzítse az útvonalhoz leképezett vezérlő metódusok előzetes és utólagos feldolgozását / taxifare -ban meghatározott TaxiFareController osztály.
A @Configuration nyilvános osztály TaxiFareMVCConfig hajtja végre a WebMvcConfigurer {@Autowired private TaxiFareRequestInterceptor taxiFareRequestInterceptor; @Orride public void addInterceptors (InterceptorRegistry registry) {register.addInterceptor (taxiFareRequestInterceptor) .addPathPatterns ("/ ** / taxifare / ** /"); }}
Összegzésképpen: WebMvcConfigurer hozzáteszi a TaxiFareRequestInterceptor belül az MVC életciklusa meghívással addInterceptors () módszer.
A legnagyobb kihívás az, hogy megszerezzük a kérelem és a válasz hasznos terhelésének másolatait a naplózáshoz, és a szervlet számára továbbra is a kért hasznos terhet hagyjuk feldolgozásra.
Az olvasási kérelem fő kérdése, hogy amint a bemeneti adatfolyamot először olvassák el, elfogyasztottként jelölik meg, és nem olvasható újra.
Az alkalmazás kivételt vet a kérésfolyam elolvasása után:
{"időbélyeg": 1500645243383, "status": 400, "error": "Bad Request", "kivétel": "org.springframework.http.converter .HttpMessageNotReadableException", "message": "Nem sikerült elolvasni a dokumentumot: A patak bezárult ; beágyazott kivétel a java.io.IOException: Stream closed "," path ":" / rest-log / taxifare / calc / "}
Ennek a problémának a leküzdésére, kihasználhatjuk a gyorsítótárat a kérelemfolyam tárolására és naplózáshoz.
A Spring néhány hasznos osztályt kínál, mint például a ContentCachingRequestWrapper és a ContentCachingResponseWrapper, amelyek felhasználhatók a kérési adatok gyorsítótárazásához naplózás céljából.
Állítsuk be preHandle () nak,-nek TaxiRideRequestInterceptor osztály a kérelemobjektum gyorsítótárazásával ContentCachingRequestWrapper osztály.
@Orride public boolean preHandle (HttpServletRequest kérés, HttpServletResponse válasz, Objektumkezelő) {HttpServletRequest requestCacheWrapperObject = new ContentCachingRequestWrapper (kérés); requestCacheWrapperObject.getParameterMap (); // Az inputStream beolvasása a requestCacheWrapperObject fájlból és naplózása a true true értékkel; }
Mint láthatjuk, a kérelemobjektumot gyorsítótáraztuk a használatával ContentCachingRequestWrapper osztály, amellyel a tényleges kérelemobjektum megzavarása nélkül olvasható a hasznos adatok a naplózáshoz:
requestCacheWrapperObject.getContentAsByteArray ();
Korlátozás
- ContentCachingRequestWrapper osztály csak a következőket támogatja:
Tartalom-típus: application / x-www-form-urlencoded Módszer-típus: POST
- A következő módszert kell használnunk annak biztosítására, hogy a kérelem adatai gyorsítótárban legyenek ContentCachingRequestWrapper használata előtt:
requestCacheWrapperObject.getParameterMap ();
5. Tavaszi beépített kérelem naplózása
A Spring beépített megoldást kínál a hasznos terhek naplózására. Kész szűrőket használhatunk, ha konfigurációt használva csatlakoztatjuk a Spring alkalmazást.
AbstractRequestLoggingFilter egy szűrő, amely biztosítja a naplózás alapfunkcióit. Az alosztályoknak felül kell írniuk a beforeRequest () és afterRequest () módszerek a kérelem körüli tényleges naplózás végrehajtására.
A Spring framework három konkrét megvalósítási osztályt kínál, amelyek felhasználhatók a beérkező kérések naplózására. Ez a három osztály a következő:
- CommonsRequestLoggingFilter
- Log4jNestedDiagnosticContextFilter (elavult)
- ServletContextRequestLoggingFilter
Most térjünk át a CommonsRequestLoggingFilter és konfigurálja a bejövő naplózási kérelem rögzítésére.
5.1. Konfigurálja a Spring Boot alkalmazást
A Spring Boot alkalmazás konfigurálható egy babdefiníció hozzáadásával a kérelem naplózásának engedélyezéséhez:
@Configuration public class RequestLoggingFilterConfig {@Bean public CommonsRequestLoggingFilter logFilter () {CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter (); filter.setIncludeQueryString (true); filter.setIncludePayload (true); filter.setMaxPayloadLength (10000); filter.setIncludeHeaders (hamis); filter.setAfterMessagePrefix ("ADATKÉRÉS:"); visszatérő szűrő; }}
Ez a naplózási szűrő megköveteli, hogy a naplószint DEBUG legyen. Engedélyezhetjük a DEBUG módot az alábbi elem hozzáadásával logback.xml:
A DEBUG szintű napló engedélyezésének másik módja az alábbiak hozzáadása alkalmazás.tulajdonságok:
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter = DEBUG
5.2. Konfigurálja a hagyományos webalkalmazást
A szokásos tavaszi webalkalmazásban Szűrő beállítható XML vagy Java konfigurációval. Állítsuk be a CommonsRequestLoggingFilter hagyományos Java alapú konfigurációval.
Mint tudjuk, a includePayload attribútuma CommonsRequestLoggingFilter alapértelmezés szerint hamis értékre van állítva. Szükségünk lenne egy egyedi osztályra, amely felülbírálja az attribútum értékét az engedélyezéshez includePayload mielőtt a Java konfigurációval befecskendezne a tartályba:
public class CustomeRequestLoggingFilter kiterjeszti a CommonsRequestLoggingFilter {public CustomeRequestLoggingFilter () {super.setIncludeQueryString (true); super.setIncludePayload (true); super.setMaxPayloadLength (10000); }}
Most be kell adnunk a CustomeRequestLoggingFilter Java alapú webes inicializáló használatával:
public class CustomWebAppInitializer implementálja a WebApplicationInitializer {public void onStartup (ServletContext container) {AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext (); context.setConfigLocation ("com.baeldung"); container.addListener (új ContextLoaderListener (context)); ServletRegistration.Dynamic diszpécser = container.addServlet ("diszpécser", új DispatcherServlet (kontextus)); diszpécser.setLoadOnStartup (1); diszpécser.addMapping ("/"); container.addFilter ("customRequestLoggingFilter", CustomeRequestLoggingFilter.class) .addMappingForServletNames (null, hamis, "diszpécser"); }}
6. Példa a cselekvésben
Most összekapcsolhatjuk a tavaszi rendszerindítást kontextussal, és működés közben láthatjuk, hogy a beérkező kérések naplózása a várt módon működik:
@Test public void givenRequest_whenFetchTaxiFareRateCard_thanOK () {TestRestTemplate testRestTemplate = new TestRestTemplate (); TaxiRide taxiRide = új TaxiRide (igaz, 10l); String viteldíj = testRestTemplate.postForObject (URL + "kiszámítja /", taxiRide, String.osztály); assertThat (viteldíj, egyenlőTo ("200")); }
7. Következtetés
Ebben a cikkben bemutattuk, hogyan lehet megvalósítani az internetes kérések naplózását elfogók segítségével; megmutattuk ennek a megoldásnak a korlátait és kihívásait is.
Ezután bemutattuk a beépített szűrőosztályt, amely használatra kész és egyszerű naplózási mechanizmust biztosít.
Mint mindig, a példa és a kódrészletek megvalósítása elérhető a GitHubon.