A HttpServletRequest többszörös olvasása tavasszal

1. Bemutatkozás

Ebben az oktatóanyagban megtanuljuk, hogyan kell olvasni a testet a HttpServletRequest többször a Spring használatával.

HttpServletRequest egy olyan felület, amely leleplezi getInputStream () módszer a test leolvasására. Alapértelmezés szerint, az ebből származó adatok InputStream csak egyszer olvasható.

2. Maven-függőségek

Az első dolog, amire szükségünk lesz, az a megfelelő tavasz-webmvc és javax.servlet függőségek:

 org.springframework spring-webmvc 5.2.0.RELEASE javax.servlet javax.servlet-api 4.0.1 

Továbbá, mivel a alkalmazás / json tartalomtípus, az jackson-databind függőség szükséges:

 com.fasterxml.jackson.core jackson-databind 2.10.0 

A Spring ezt a könyvtárat használja a JSON-ba történő konvertáláshoz.

3. Tavaszi ContentCachingRequestWrapper

A tavasz biztosítja a ContentCachingRequestWrapper osztály. Ez az osztály egy módszert biztosít, getContentAsByteArray () hogy többször elolvassa a testet.

Ennek az osztálynak van korlátozása, bár: Nem olvashatjuk el többször a testet a getInputStream () és getReader () mód.

Ez az osztály gyorsítótárba helyezi a kéréstestet a InputStream. Ha elolvassuk a InputStream az egyik szűrőben, akkor a szűrő lánc többi következő szűrője már nem tudja olvasni. E korlátozás miatt ez az osztály nem alkalmas minden helyzetben.

Ennek a korlátnak a leküzdése érdekében most nézzünk meg egy általánosabb megoldást.

4. Hosszabbítás HttpServletRequest

Hozzunk létre egy új osztály - CachedBodyHttpServletRequest - amely kiterjed HttpServletRequestWrapper. Így nem kell felülírnunk a HttpServletRequest felület.

HttpServletRequestWrapper osztály két elvont módszerrel rendelkezik getInputStream () és getReader (). Mindkét módszert felülírjuk, és létrehozunk egy új konstruktort.

4.1. A kivitelező

Először hozzunk létre egy konstruktort. Belül leolvassuk a testet a ténylegesből InputStream és tárolja a byte[] tárgy:

public class CachedBodyHttpServletRequest kiterjeszti a HttpServletRequestWrapper {private byte [] cachedBody; public CachedBodyHttpServletRequest (HttpServletRequest kérés) dobja az IOException {super (kérés); InputStream requestInputStream = request.getInputStream (); this.cachedBody = StreamUtils.copyToByteArray (requestInputStream); }}

Ennek eredményeként többször is leolvashatjuk a testet.

4.2. getInputStream ()

Ezután írjuk felül a getInputStream () módszer. Ezt a módszert fogjuk használni a nyers törzs beolvasásához és objektummá alakításához.

Ebben a módszerben megtesszük hozzon létre és adjon vissza egy új objektumot CachedBodyServletInputStream osztály (a ServletInputStream):

@Orride public ServletInputStream getInputStream () dobja az IOException-t {return new CachedBodyServletInputStream (this.cachedBody); }

4.3. getReader ()

Akkor felülírjuk a getReader () módszer. Ez a módszer a BufferedReader tárgy:

@Orride public BufferedReader getReader () dobja az IOException {ByteArrayInputStream byteArrayInputStream = új ByteArrayInputStream (this.cachedBody); return new BufferedReader (új InputStreamReader (byteArrayInputStream)); }

5. Végrehajtása ServletInputStream

Hozzunk létre egy osztály - CachedBodyServletInputStream - amely megvalósítja ServletInputStream. Ebben az osztályban létrehozunk egy új konstruktort, és felülírjuk a befejeződött(), készen van() és olvas() mód.

5.1. A kivitelező

Először hozzunk létre egy új konstruktort, amely egy bájt tömböt vesz fel.

Belül létrehozunk egy új ByteArrayInputStream a bájt tömböt használva. Ezt követően hozzárendeljük a globális változóhoz cachedBodyInputStream:

public class CachedBodyServletInputStream kiterjeszti a ServletInputStream {private InputStream cachedBodyInputStream; public CachedBodyServletInputStream (byte [] cachedBody) {this.cachedBodyInputStream = új ByteArrayInputStream (cachedBody); }}

5.2. olvas()

Ezután felülírjuk a olvas() módszer. Ebben a módszerben felhívjuk ByteArrayInputStream # olvasása:

@Orride public int read () dob IOException {return cachedBodyInputStream.read (); }

5.3. befejeződött()

Ezután felülírjuk a befejeződött() módszer. Ez a módszer jelzi, hogy InputStream több adat van elolvasva vagy sem. Visszatér igaz amikor nulla bájt olvasható:

@Orride public boolean isFinished () {return cachedBody.available () == 0; }

5.4. készen van()

Hasonlóképpen felülírjuk a készen van() módszer. Ez a módszer jelzi, hogy InputStream készen áll az olvasásra, vagy sem.

Mivel már másoltuk InputStream egy bájtos tömbben visszatérünk igaz jelezni, hogy mindig elérhető:

@Orride public boolean isReady () {return true; }

6. A szűrő

Végül hozzunk létre egy új szűrőt a CachedBodyHttpServletRequest osztály. Itt kibővítjük a tavaszit OncePerRequestFilter osztály. Ennek az osztálynak van egy elvont módszere doFilterInternal ().

Ebben a módszerben megtesszük hozzon létre egy objektumot a CachedBodyHttpServletRequest osztály a tényleges kérelem objektumból:

CachedBodyHttpServletRequest cachedBodyHttpServletRequest = új CachedBodyHttpServletRequest (kérés);

Akkor majd adja át ezt az új kérésburkoló objektumot a szűrőláncnak. Tehát az összes következő hívás a getInputStream() metódus meghívja az felülbírált metódust:

filterChain.doFilter (cachedContentHttpServletRequest, válasz);

7. Következtetés

Ebben az oktatóanyagban gyorsan végigjártuk a ContentCachingRequestWrapper osztály. Láttuk a korlátait is.

Ezután létrehoztuk a HttpServletRequestWrapper osztály. Felülírtuk a getInputStream () metódus az objektum visszaküldéséhez ServletInputStream osztály.

Végül létrehoztunk egy új szűrőt, hogy továbbítsuk a kérésburkoló objektumot a szűrőlánchoz. Tehát többször elolvashattuk a kérést.

A példák teljes forráskódja megtalálható a GitHub oldalon.


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