Proljeće - prijavite dolazne zahtjeve

1. Uvod

U ovom brzom vodiču prikazat ćemo osnove zapisivanja dolaznih zahtjeva pomoću Springinog filtra za bilježenje. Ako tek započinjete s prijavom, pogledajte ovaj uvodni članak o prijavljivanju, kao i članak SLF4J.

2. Ovisnosti Mavena

Ovisnosti evidentiranja jednostavno će biti jednake onima u uvodnom članku; dodajmo ovdje jednostavno Proljeće:

 org.springframework opruga-jezgra 5.2.2.OSLOBOĐENJE 

Najnoviju verziju možete pronaći ovdje za spring-core.

3. Osnovni web kontroler

Prije svega, definirajmo kontroler koji će se koristiti u našem primjeru:

@RestController javna klasa TaxiFareController {@GetMapping ("/ taxifare / get /") public RateCard getTaxiFare () {return new RateCard (); } @PostMapping ("/ taxifare / izračunaj /") javni niz convertTaxiFare (@RequestBody @Valid TaxiRide taxiRide) {// vrati izračunatu cijenu}}

4. Prilagođeno bilježenje zahtjeva

Spring pruža mehanizam za konfiguriranje korisnički definiranih presretača za izvođenje radnji prije i nakon web zahtjeva.

Među presretačima zahtjeva Spring, jedno od značajnih sučelja je HandlerInterceptor, koji se može koristiti za bilježenje dolaznog zahtjeva primjenom sljedećih metoda:

  1. preHandle () - ova se metoda izvršava prije stvarne metode usluge kontrolera
  2. afterCompletion () - ova se metoda izvršava nakon što je kontroler spreman poslati odgovor

Nadalje, Spring pruža zadanu implementaciju HandlerInterceptor sučelje u obliku HandlerInterceptorAdaptor klase koju korisnik može proširiti.

Stvorimo vlastiti presretač - širenjem HandlerInterceptorAdaptor kao:

@Component javna klasa TaxiFareRequestInterceptor proširuje HandlerInterceptorAdapter {@Override javni boolean preHandle (HttpServletRequest zahtjev, HttpServletResponse odgovor, Obradnik objekta) {return true; } @Override javna praznina afterCompletion (zahtjev HttpServletRequest, odgovor HttpServletResponse, rukovatelj objektima, izuzetak ex) {//}}

Na kraju ćemo konfigurirati TaxiRideRequestInterceptor unutar MVC životnog ciklusa za bilježenje pre i naknadne obrade poziva metode kontrolera koji se preslikavaju na put / taxifare definirano u TaxiFareController razred.

@Configuration javna klasa TaxiFareMVCConfig implementira WebMvcConfigurer {@Autowired private TaxiFareRequestInterceptor taxiFareRequestInterceptor; @Override public void addInterceptors (registar InterceptorRegistry) {registry.addInterceptor (taxiFareRequestInterceptor) .addPathPatterns ("/ ** / taxifare / ** /"); }}

U zaključku, WebMvcConfigurer dodaje TaxiFareRequestInterceptor unutar opruge MVC životni ciklus pozivanjem addInterceptors () metoda.

Najveći je izazov dobiti kopije zahtjeva i odgovora za prijavu za bilježenje, a traženi teret i dalje ostaviti da ga servlet obradi.

Glavni problem zahtjeva za čitanje je taj što se čim se ulazni tok pročita prvi put, označi kao potrošen i ne može se ponovno čitati.

Aplikacija će izbaciti iznimku nakon čitanja prijenosa zahtjeva:

{"timestamp": 1500645243383, "status": 400, "error": "Bad Request", "iznimka": "org.springframework.http.converter .HttpMessageNotReadableException", "message": "Nije moguće pročitati dokument: tok je zatvoren ; ugniježđena iznimka je java.io.IOException: Tok je zatvoren "," put ":" / rest-log / taxifare / izračun / "}

Da biste prevladali ovaj problem, možemo iskoristiti predmemoriranje za pohranu tijeka zahtjeva i korištenje za bilježenje.

Spring pruža nekoliko korisnih klasa kao što su ContentCachingRequestWrapper i ContentCachingResponseWrapper koji se mogu koristiti za predmemoriranje podataka zahtjeva u svrhu evidentiranja.

Prilagodimo svoje preHandle () od TaxiRideRequestInterceptor class za predmemoriranje objekta zahtjeva pomoću ContentCachingRequestWrapper razred.

@Override javni logički preHandle (zahtjev HttpServletRequest, odgovor HttpServletResponse, rukovatelj objektom) {HttpServletRequest requestCacheWrapperObject = novi ContentCachingRequestWrapper (zahtjev); requestCacheWrapperObject.getParameterMap (); // Pročitajte inputStream iz requestCacheWrapperObject i prijavite da se vraća true; }

Kao što možemo vidjeti, predmemorirali smo objekt zahtjeva pomoću ContentCachingRequestWrapper klasa koja se može koristiti za čitanje podataka korisnog tereta za bilježenje bez ometanja stvarnog objekta zahtjeva:

requestCacheWrapperObject.getContentAsByteArray ();

Ograničenje

  • ContentCachingRequestWrapper klasa podržava samo sljedeće:
Tip sadržaja: application / x-www-form-urlencoded Tip metode: POST
  • Moramo se pozvati na sljedeću metodu kako bismo osigurali da se podaci zahtjeva keširaju ContentCachingRequestWrapper prije nego što ga upotrijebite:
requestCacheWrapperObject.getParameterMap ();

5. Upis ugrađenih zahtjeva za proljeće

Spring pruža ugrađeno rješenje za bilježenje korisnog tereta. Gotove filtre možemo koristiti uključivanjem programa Spring u konfiguraciju.

AbstractRequestLoggingFilter je filtar koji pruža osnovne funkcije bilježenja. Podrazredi bi trebali nadjačati beforeRequest () i afterRequest () metode za izvođenje stvarnog zapisivanja oko zahtjeva.

Spring framework pruža tri konkretne klase implementacije koje se mogu koristiti za evidentiranje dolaznog zahtjeva. Ova tri razreda su:

  • CommonsRequestLoggingFilter
  • Log4jNestedDiagnosticContextFilter (zastarjelo)
  • ServletContextRequestLoggingFilter

Idemo sada na CommonsRequestLoggingFilter i konfigurirajte ga da uhvati dolazni zahtjev za prijavu.

5.1. Konfigurirajte Spring Boot Application

Aplikacija Spring Boot može se konfigurirati dodavanjem definicije graha kako bi se omogućilo evidentiranje zahtjeva:

@Configuration javna klasa RequestLoggingFilterConfig {@Bean public CommonsRequestLoggingFilter logFilter () {CommonsRequestLoggingFilter filter = novi CommonsRequestLoggingFilter (); filter.setIncludeQueryString (true); filter.setIncludePayload (true); filter.setMaxPayloadLength (10000); filter.setIncludeHeaders (false); filter.setAfterMessagePrefix ("ZAHTJEVI PODATKE:"); povratni filter; }}

Također, ovaj filtar zapisivanja zahtijeva da se razina dnevnika postavi na DEBUG. Način DEBUG možemo omogućiti dodavanjem donjeg elementa u logback.xml:

Drugi način omogućavanja zapisnika razine DEBUG je dodavanje sljedećeg u primjena.svojstva:

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

5.2. Konfiguriranje tradicionalne web aplikacije

U standardnoj web aplikaciji Spring, filtar može se postaviti putem XML ili Java konfiguracije. Postavimo CommonsRequestLoggingFilter koristeći uobičajenu Java konfiguraciju.

Kao što znamo, includePayload atribut CommonsRequestLoggingFilter je prema zadanim postavkama postavljeno na false. Trebat će nam prilagođena klasa koja će nadjačati vrijednost atributa da bi se omogućila includePayload prije ubrizgavanja u spremnik pomoću Java konfiguracije:

javna klasa CustomeRequestLoggingFilter proširuje CommonsRequestLoggingFilter {public CustomeRequestLoggingFilter () {super.setIncludeQueryString (true); super.setIncludePayload (true); super.setMaxPayloadLength (10000); }}

Sada moramo ubrizgati CustomeRequestLoggingFilter pomoću web inicijalizatora temeljenog na Javi:

javna klasa CustomWebAppInitializer provodi WebApplicationInitializer {javna praznina onStartup (spremnik ServletContext) {AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext (); context.setConfigLocation ("com.baeldung"); container.addListener (novi ContextLoaderListener (kontekst)); ServletRegistration.Dynamic dispečer = container.addServlet ("dispečer", novi DispatcherServlet (kontekst)); dispečer.setLoadOnStartup (1); dispečer.addMapping ("/"); container.addFilter ("customRequestLoggingFilter", CustomeRequestLoggingFilter.class) .addMappingForServletNames (null, false, "dispečer"); }}

6. Primjer na djelu

Sada možemo povezati Spring Boot s kontekstom i vidjeti na djelu da bilježenje dolaznih zahtjeva radi kako se očekuje:

@Test javna praznina givenRequest_whenFetchTaxiFareRateCard_thanOK () {TestRestTemplate testRestTemplate = nova TestRestTemplate (); TaxiRide taxiRide = novi TaxiRide (istina, 10l); String fare = testRestTemplate.postForObject (URL + "izračunaj /", taxiRide, String.class); assertThat (cijena, jednakaTo ("200")); }

7. Zaključak

U ovom smo članku pokazali kako implementirati osnovno zapisivanje web zahtjeva pomoću presretača; pokazali smo i ograničenja i izazove ovog rješenja.

Zatim smo pokazali ugrađenu klasu filtra koja pruža spreman za upotrebu i jednostavan mehanizam za prijavu.

Kao i uvijek, implementacija primjera i isječci koda dostupni su na GitHubu.


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