Udalosti odoslané serverom (SSE) v JAX-RS

1. Prehľad

Server-Sent Events (SSE) je špecifikácia založená na protokole HTTP, ktorá poskytuje spôsob nadviazania dlhodobého a jednokanálového pripojenia zo servera na klienta.

Klient inicializuje pripojenie SSE pomocou typu média text / stream udalostí v súhlasiť hlavička.

Neskôr sa automaticky aktualizuje bez vyžiadania servera.

Viac podrobností o špecifikácii môžeme skontrolovať na oficiálnej špecifikácii.

V tomto tutoriáli si predstavíme novú implementáciu SSE JAX-RS 2.1.

Preto sa pozrieme na to, ako môžeme publikovať udalosti pomocou API servera JAX-RS. Tiež preskúmame, ako ich môžeme spotrebovať buď prostredníctvom rozhrania JAX-RS Client API, alebo iba pomocou klienta HTTP, ako je zvlnenie nástroj.

2. Porozumenie udalostiam SSE

Udalosť SSE je blok textu zložený z nasledujúcich polí:

  • Udalosť: typ udalosti. Server môže odosielať veľa správ rôznych typov a klient môže počúvať iba konkrétny typ alebo môže každý typ udalosti spracovať odlišne
  • Údaje: správa odoslaná serverom. Pre tú istú udalosť môžeme mať veľa dátových liniek
  • Id: ID udalosti, použité na odoslanie ID poslednej udalosti hlavička, po opakovaní spojenia. Je to užitočné, pretože môže zabrániť serveru v odosielaní už odoslaných udalostí
  • Skúsiť znova: čas v milisekundách, počas ktorého má klient nadviazať nové pripojenie pri strate prúdu. Posledné prijaté ID sa automaticky odošle cez internet ID poslednej udalosti hlavička
  • :„: Toto je komentár a klient ho ignoruje

Dve po sebe nasledujúce udalosti sú tiež oddelené dvojitým novým riadkom „\ n \ n‘.

Dáta v tej istej udalosti môžu byť navyše zapísané do mnohých riadkov, ako je vidieť v nasledujúcom príklade:

udalosť: skladové ID: 1: zmena ceny opakovať: 4 000 údajov: {"dateTime": "2018-07-14T18: 06: 00.285", "id": 1, údaje: "name": "GOOG", "price" : 75.7119} event: stock id: 2: pokus o zmenu ceny: 4000 údajov: {"dateTime": "2018-07-14T18: 06: 00.285", "id": 2, "name": "IBM", "cena ": 83.4611}

V JAX RS, udalosť SSE je abstrahovaná SseEvent rozhranie, alebo presnejšie dvoma rozhraniami OutboundSseEvent a InboundSseEvent.

Kým OutboundSseEvent sa používa na serverovom API a navrhuje odoslanú udalosť, InboundSseEvent sa používa v rozhraní API klienta a abstrahuje prijatú udalosť.

3. Publikovanie udalostí SSE

Teraz, keď sme diskutovali o tom, čo je udalosť SSE, pozrime sa, ako ju môžeme zostaviť a poslať ju klientovi HTTP.

3.1. Nastavenie projektu

Už máme návod na nastavenie projektu Maven založeného na JAX RS. Pokojne sa tam pozrite, ako nastaviť závislosti a začať s JAX RS.

3.2. Metóda zdrojov SSE

Metóda SSE Resource je metóda JAX RS, ktorá:

  • Môže vyrobiť a text / stream udalostí Typ média
  • Má injekciu SseEventSink parameter, kam sa udalosti posielajú
  • Môže mať aj injekciu Sse parameter, ktorý sa používa ako vstupný bod na vytvorenie nástroja na tvorbu udalostí
@GET @Path ("prices") @Produces ("text / event-stream") public void getStockPrices (@Context SseEventSink sseEventSink, @Context Sse sse) {// ...}

V dôsledku toho by mal klient urobiť prvú požiadavku HTTP s nasledujúcou hlavičkou HTTP:

Prijať: text / stream udalostí 

3.3. Inštancia SSE

Inštancia SSE je kontextová fazuľa, ktorú produkt JAX RS Runtime sprístupní pre injekciu.

Mohli by sme to použiť ako továreň na vytvorenie:

  • OutboundSseEvent.Builder - nám umožňuje vytvárať udalosti potom
  • SseBroadcaster - umožňuje vysielať udalosti viacerým predplatiteľom

Pozrime sa, ako to funguje:

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

Teraz sa zameriame na nástroj na tvorbu udalostí. OutboundSseEvent.Builder je zodpovedný za vytvorenie OutboundSseEvent:

OutboundSseEvent sseEvent = this.eventBuilder .name ("stock") .id (String.valueOf (lastEventId)) .mediaType (MediaType.APPLICATION_JSON_TYPE) .data (Stock.class, stock) .reconnectDelay (4000) .comment ("zmena ceny" ") .build ();

Ako vidíme, staviteľ má metódy na nastavenie hodnôt pre všetky polia udalostí zobrazené vyššie. Okrem toho Typ média() metóda sa používa na serializáciu objektu Java dátového poľa do vhodného textového formátu.

V predvolenom nastavení je typ média dátového poľa text / obyčajný. Preto pri práci s. Nemusí byť výslovne špecifikované String Dátový typ.

V opačnom prípade, ak chceme spracovať vlastný objekt, musíme určiť typ média alebo poskytnúť vlastný MessageBodyWriter.JAX RS Runtime poskytuje MessageBodyWriters pre najznámejšie typy médií.

Inštancia Sse má aj dve klávesové skratky pre vytváranie udalostí iba s údajovým poľom alebo typovými a údajovými poľami:

OutboundSseEvent sseEvent = sse.newEvent ("super udalosť"); OutboundSseEvent sseEvent = sse.newEvent ("zadaná udalosť", "dátová udalosť");

3.4. Posiela sa jednoduchá udalosť

Teraz, keď vieme, ako vytvárať udalosti, a rozumieme tomu, ako funguje SSE zdroj. Poďme poslať jednoduchú udalosť.

The SseEventSink rozhranie abstrahuje jediné pripojenie HTTP. Modul JAX-RS Runtime ho môže sprístupniť iba prostredníctvom injekcie v metóde prostriedkov SSE.

Odoslanie udalosti je potom také jednoduché ako vyvolanie SseEventSink.poslať ().

V nasledujúcom príklade odošle množstvo aktualizácií akcií a nakoniec zavrie stream udalostí:

@GET @Path ("price") @Produces ("text / event-stream") public void getStockPrices (@Context SseEventSink sseEventSink /*..*/) {int lastEventId = // ..; while (running) {Stock stock = stockService.getNextTransaction (lastEventId); if (stock! = null) {OutboundSseEvent sseEvent = this.eventBuilder .name ("stock") .id (String.valueOf (lastEventId)) .mediaType (MediaType.APPLICATION_JSON_TYPE) .data (Stock.class, stock) .reconnectDelay ( 3000). Komentár („zmena ceny“). Build (); sseEventSink.send (sseEvent); lastEventId ++; } // ..} sseEventSink.close (); }

Po odoslaní všetkých udalostí server ukončí spojenie buď explicitným vyvolaním súboru Zavrieť() metódou alebo najlepšie použitím skúsiť so zdrojom, ako SseEventSink rozširuje Automatické uzatváranie rozhranie:

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

V našej ukážkovej aplikácii to môžeme vidieť, ak navštívime:

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

3.5. Vysielacie udalosti

Vysielanie je proces, pomocou ktorého sa udalosti odosielajú viacerým klientom súčasne. Toho sa dosahuje prostredníctvom SseBroadcaster API a vykonáva sa to v troch jednoduchých krokoch:

Najskôr vytvoríme SseBroadcaster objekt z vloženého kontextu Sse, ako je uvedené vyššie:

SseBroadcaster sseBroadcaster = sse.newBroadcaster ();

Potom by sa klienti mali prihlásiť na odber, aby mohli prijímať udalosti SSE. Spravidla sa to robí metódou zdroja SSE, kde a SseEventSink je vložená kontextová inštancia:

@GET @Path ("prihlásiť sa na odber") @Produces (MediaType.SERVER_SENT_EVENTS) public void listen (@Context SseEventSink sseEventSink) {this.sseBroadcaster.register (sseEventSink); }

A nakoniec, zverejnenie udalosti môžeme spustiť vyvolaním súboru vysielanie () metóda:

@GET @Path ("zverejniť") public void broadcast () {OutboundSseEvent sseEvent = // ...; this.sseBroadcaster.broadcast (sseEvent); }

Každému registrovanému sa tým pošle rovnaká udalosť SseEventSink.

Na predstavenie vysielania môžeme získať prístup na túto adresu URL:

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

Potom môžeme spustiť vysielanie vyvolaním metódy zdroja broadcast ():

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

4. Konzumácia udalostí SSE

Na využitie udalosti SSE odoslanej serverom môžeme použiť ľubovoľného klienta HTTP, ale pre tento tutoriál použijeme rozhranie API klienta JAX RS.

4.1. Klientske rozhranie JAX RS pre SSE

Ak chcete začať s API klienta pre SSE, musíme poskytnúť závislosti pre implementáciu klienta JAX RS.

Tu použijeme implementáciu klienta Apache CXF:

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

The SseEventSource je srdcom tohto API a je skonštruovaný z WebTarget.

Začíname počúvaním prichádzajúcich udalostí, ktoré sú abstrahované znakom InboundSseEvent rozhranie:

Klient klient = ClientBuilder.newClient (); Cieľ WebTarget = client.target (url); try (SseEventSource source = SseEventSource.target (target) .build ()) {source.register ((inboundSseEvent) -> System.out.println (inboundSseEvent)); source.open (); }

Po nadviazaní spojenia bude pre každý prijatý hovor vyvolaný registrovaný spotrebiteľ udalosti InboundSseEvent.

Potom môžeme použiť readData () metóda na načítanie pôvodných údajov Reťazec:

Reťazec data = inboundSseEvent.readData ();

Alebo môžeme použiť preťaženú verziu na získanie Deserializovaného Java objektu pomocou vhodného typu média:

Stock stock = inboundSseEvent.readData (Stock.class, MediaType.Application_Json);

Tu sme poskytli iba jednoduchého spotrebiteľa udalostí, ktorý vytlačil prichádzajúcu udalosť v konzole.

5. Záver

V tomto tutoriáli sme sa zamerali na to, ako používať udalosti odoslané serverom v JAX RS 2.1. Poskytli sme príklad, ktorý ukazuje, ako posielať udalosti jednému klientovi, ako aj vysielať udalosti viacnásobným klientom.

Nakoniec sme tieto udalosti spotrebovali pomocou klientskeho rozhrania API JAX-RS.

Ako obvykle, kód tohto tutoriálu nájdete na Githube.


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