Kiszolgáló által küldött események (SSE) a JAX-RS-ben

1. Áttekintés

A Server-Sent Events (SSE) egy HTTP alapú specifikáció, amely módot nyújt a szerver és az ügyfél közötti hosszú távú és egycsatornás kapcsolat létrehozására.

Az ügyfél a médiatípus használatával kezdeményezi az SSE-kapcsolatot szöveg / eseményfolyam ban,-ben Elfogad fejléc.

Később automatikusan frissül a szerver kérése nélkül.

A specifikációról további részleteket a hivatalos specifikációban ellenőrizhetünk.

Ebben az oktatóanyagban bemutatjuk az SSE új JAX-RS 2.1 megvalósítását.

Ezért megvizsgáljuk, hogyan tehetünk közzé eseményeket a JAX-RS Server API-val. Azt is meg fogjuk vizsgálni, hogy miként fogyaszthatjuk őket akár a JAX-RS Client API, akár egy olyan HTTP kliens által, mint a becsavar eszköz.

2. Az SSE események megértése

Az SSE esemény a következő mezőkből álló szövegblokk:

  • Esemény: az esemény típusa. A szerver sok különböző típusú üzenetet küldhet, és az ügyfél csak egy adott típust hallgathat meg, vagy az egyes eseménytípusokat másképp tudja feldolgozni
  • Adat: a szerver által küldött üzenet. Sok adatsorunk lehet ugyanarra az eseményre
  • Id: az esemény azonosítója, a Utolsó esemény-azonosító fejléc, a kapcsolat újrapróbálkozása után. Hasznos, mivel megakadályozhatja a kiszolgálót a már elküldött események küldésében
  • Próbálja újra: az idő milliszekundumban, ameddig az ügyfél új kapcsolatot létesít, amikor az áram elvész. Az utoljára kapott azonosítót automatikusan elküldi a Utolsó esemény-azonosító fejléc
  • :’: Ez egy megjegyzés, amelyet az ügyfél figyelmen kívül hagy

Két egymást követő eseményt kettős új sor választ el\ n \ n‘.

Ezenkívül ugyanabban az eseményben az adatok sok sorba írhatók, amint az a következő példában látható:

event: készletazonosító: 1: árváltozás újrapróbálkozása: 4000 adat: {"dateTime": "2018-07-14T18: 06: 00.285", "id": 1, data: "name": "GOOG", "price" : 75.7119} event: stock id: 2: árváltozás újrapróbálkozása: 4000 adat: {"dateTime": "2018-07-14T18: 06: 00.285", "id": 2, "name": "IBM", "price ": 83.4611}

Ban ben JAX RS, egy SSE eseményt a SseEvent felület, pontosabban a két alfelület által OutboundSseEvent és InboundSseEvent.

Amíg a OutboundSseEvent a kiszolgáló API-n található, és megtervez egy elküldött eseményt, a InboundSseEvent a Client API használja, és kivonatol egy fogadott eseményt.

3. SSE események közzététele

Most, hogy megbeszéltük, mi egy SSE esemény, nézzük meg, hogyan készíthetjük el és küldhetjük el egy HTTP kliensnek.

3.1. Projekt beállítása

Már van egy bemutatónk a JAX RS-alapú Maven projekt beállításáról. Bátran nézzen oda, hogyan állíthatja be a függőségeket, és kezdje el a JAX RS-t.

3.2. SSE erőforrás módszer

Az SSE erőforrás módszer egy JAX RS módszer, amely:

  • Képes előállítani a szöveg / eseményfolyam média típus
  • Van injekció SseEventSink paraméter, ahová az eseményeket elküldik
  • Lehet injekciót is beadni Sse paraméter, amelyet belépési pontként használnak egy eseménykészítő létrehozásához
@GET @Path ("árak") @Produces ("text / event-stream") public void getStockPrices (@Context SseEventSink sseEventSink, @Context Sse sse) {// ...}

Ennek következtében az ügyfélnek meg kell adnia az első HTTP-kérést a következő HTTP-fejléccel:

Elfogadás: szöveg / eseményfolyam 

3.3. Az SSE-példány

Az SSE példány egy olyan kontextus bab, amelyet a JAX RS Runtime injekciózásra bocsát rendelkezésre.

Gyárként felhasználhatnánk a következők létrehozására:

  • OutboundSseEvent.Builder - lehetővé teszi számunkra, hogy eseményeket hozzunk létre akkor
  • SseBroadcaster - lehetővé teszi számunkra, hogy eseményeket közvetítsünk több előfizető számára

Nézzük meg, hogyan működik:

@Context public void setSse (Sse sse) {this.sse = sse; this.eventBuilder = sse.newEventBuilder (); this.sseBroadcaster = sse.newBroadcaster (); }

Most összpontosítsunk az eseményépítőre. OutboundSseEvent.Builder felelős a OutboundSseEvent:

OutboundSseEvent sseEvent = this.eventBuilder .name ("stock") .id (String.valueOf (lastEventId)) .mediaType (MediaType.APPLICATION_JSON_TYPE) .data (Stock.class, stock) .reconnectDelay (4000) .comment ("árváltozás" ") .épít();

Ahogy látjuk, az építőnek módszerei vannak a fenti eseménymezők értékeinek beállítására. Ezenkívül a média típus() metódust alkalmazzák a Java objektum adatmező megfelelő szöveges formátumra történő sorosítására.

Alapértelmezés szerint az adatmédia adathordozó-típusa szöveg / sima. Ennélfogva nem szükséges kifejezetten meghatározni a Húr adattípus.

Ellenkező esetben, ha egyéni objektumot akarunk kezelni, meg kell adnunk a hordozótípust, vagy meg kell adnunk egy egyedi értéket MessageBodyWriter.A JAX RS Runtime biztosítja MessageBodyWriters a legismertebb médiatípusokhoz.

A Sse példánynak két építõi parancsikonja is van egy esemény létrehozásához, amely csak az adatmezõt, vagy a típust és az adatmezõt tartalmazza:

OutboundSseEvent sseEvent = sse.newEvent ("klassz esemény"); OutboundSseEvent sseEvent = sse.newEvent ("tipizált esemény", "adatesemény");

3.4. Egyszerű esemény küldése

Most, hogy tudjuk, hogyan kell eseményeket építeni, és megértjük, hogyan működik az SSE erőforrás. Küldjünk egy egyszerű eseményt.

A SseEventSink az interfész egyetlen HTTP-kapcsolatot kap. A JAX-RS Runtime csak injekcióval teheti elérhetővé az SSE erőforrás módszerben.

Egy esemény elküldése akkor egyszerű, mint a meghívás SseEventSink.Küld().

A következő példában egy csomó részvényfrissítést küld, és végül bezárja az eseményfolyamot:

@GET @Path ("árak") @Produces ("text / event-stream") public void getStockPrices (@Context SseEventSink sseEventSink /*..*/) {int lastEventId = // ..; míg (fut) {Stock stock = stockService.getNextTransaction (lastEventId); if (készlet! = null) {OutboundSseEvent sseEvent = this.eventBuilder .name ("stock") .id (String.valueOf (lastEventId)) .mediaType (MediaType.APPLICATION_JSON_TYPE) .data (Stock.class, stock) .reconnectDelay ( 3000) .megjegyzés ("árváltozás") .építés (); sseEventSink.send (sseEvent); lastEventId ++; } // ..} sseEventSink.close (); }

Az összes esemény elküldése után a kiszolgáló vagy az explicit meghívásával bezárja a kapcsolatot Bezárás() módszerrel, vagy előnyösen a próbálkozzon erőforrással, mint a SseEventSink kiterjeszti a Automatikusan zárható felület:

try (SseEventSink sink = sseEventSink) {OutboundSseEvent sseEvent = // .. sink.send (sseEvent); }

Mintaalkalmazásunkban láthatjuk ezt a futást, ha ellátogatunk:

//localhost:9080/sse-jaxrs-server/sse.html

3.5. Események közvetítése

A műsorszórás az a folyamat, amelynek során az eseményeket egyszerre több kliensnek továbbítják. Ezt a SseBroadcaster API, és három egyszerű lépésben történik:

Először létrehozzuk a SseBroadcaster objektum egy injektált Sse-kontextusból, a korábban bemutatott módon:

SseBroadcaster sseBroadcaster = sse.newBroadcaster ();

Ezután az ügyfeleknek fel kell fizetniük az Sse-események fogadására. Ez általában egy SSE erőforrás módszerben történik, ahol a SseEventSink a kontextus példányt injektálják:

@GET @Path ("előfizetés") @Produces (MediaType.SERVER_SENT_EVENTS) nyilvános érvénytelen hallgatás (@Context SseEventSink sseEventSink) {this.sseBroadcaster.register (sseEventSink); }

És végül, az esemény közzétételét a adás() módszer:

@GET @Path ("közzététel") public void broadcast () {OutboundSseEvent sseEvent = // ...; this.sseBroadcaster.broadcast (sseEvent); }

Ez ugyanazt az eseményt küldi minden regisztráltnak SseEventSink.

A műsorszolgáltatás bemutatásához elérhetjük ezt az URL-t:

//localhost:9080/sse-jaxrs-server/sse-broadcast.html

Ezután elindíthatjuk a sugárzást a broadcast () erőforrás módszer meghívásával:

curl -X GET // localhost: 9080 / sse-jaxrs-server / sse / stock / publish

4. SSE események fogyasztása

A kiszolgáló által küldött SSE események felhasználásához bármilyen HTTP klienst használhatunk, de ehhez az oktatóanyaghoz a JAX RS kliens API-t fogjuk használni.

4.1. JAX RS Client API SSE-hez

Az SSE kliens API használatának megkezdéséhez meg kell adnunk a JAX RS Client megvalósításának függőségeit.

Itt az Apache CXF kliens megvalósítását fogjuk használni:

 org.apache.cxf cxf-rt-rs-client $ {cxf-version} org.apache.cxf cxf-rt-rs-sse $ {cxf-version} 

A SseEventSource ennek az API-nak a szíve, és a The-ból épül fel Webcél.

Először a bejövő események meghallgatásával kezdjük, amelyeket a InboundSseEvent felület:

Ügyfél kliens = ClientBuilder.newClient (); WebTarget target = client.target (url); try (SseEventSource forrás = SseEventSource.target (target) .build ()) {source.register ((inboundSseEvent) -> System.out.println (inboundSseEvent)); forrás.nyit (); }

A kapcsolat létrejötte után a regisztrált eseményfogyasztót minden beérkezett hívja InboundSseEvent.

Ezután használhatjuk a readData () módszer az eredeti adatok olvasására Húr:

Karakterlánc-adatok = inboundSseEvent.readData ();

Vagy használhatjuk a túlterhelt verziót a Deserialized Java Object megszerzéséhez a megfelelő adathordozó-típus használatával:

Készletkészlet = bejövőSseEvent.readData (részvényosztály, MediaType.Application_Json);

Itt csak egy egyszerű eseményfogyasztót biztosítottunk, amely kinyomtatja a bejövő eseményt a konzolon.

5. Következtetés

Ebben az oktatóanyagban arra összpontosítottunk, hogy miként használhatjuk a Server-Sent Events alkalmazást a JAX RS 2.1-ben. Hoztunk egy példát, amely bemutatja, hogyan lehet eseményeket elküldeni egyetlen kliensnek, valamint hogyan lehet eseményeket továbbítani többszörös klienseknek.

Végül ezeket az eseményeket a JAX-RS kliens API segítségével használtuk fel.

Szokás szerint ennek az oktatóanyagnak a kódja megtalálható a Githubon.


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