Udalosti odoslané serverom na jar

1. Prehľad

V tomto výučbe sa dozvieme, ako môžeme s Springom implementovať API založené na serveri odosielaných udalostí.

Jednoducho povedané, Server-Sent-Events, alebo skrátene SSE, je štandard HTTP, ktorý umožňuje webovej aplikácii spracovávať jednosmerný prúd udalostí a prijímať aktualizácie vždy, keď server emituje údaje.

Verzia jar 4.2 to už podporovala, ale počnúc jarou 5 máme teraz idiomatickejší a pohodlnejší spôsob riešenia.

2. SSE s jarom 5 Webflux

Aby ste to dosiahli, môžeme využiť implementácie ako Flux trieda poskytovaná Reaktor knižnica alebo potenciálne ServerSentEvent subjekt, ktorá nám dáva kontrolu nad metadátami udalostí.

2.1. Streamujte udalosti pomocou Flux

Flux je reaktívna reprezentácia toku udalostí - je spracovaná odlišne na základe zadaného typu média žiadosti alebo odpovede.

Aby sme vytvorili koncový bod streamovania SSE, budeme sa musieť riadiť špecifikáciami W3C a označiť jeho typ MIME ako text / stream udalostí:

@GetMapping (cesta = "/ stream-flux", produkuje = MediaType.TEXT_EVENT_STREAM_VALUE) verejný tok streamFlux () {návrat Flux.interval (Duration.ofSeconds (1)) .map (sekvencia -> "Flux -" + LocalTime.now ().natiahnuť()); }

The interval metóda vytvára a Flux ktorý vyžaruje dlho hodnoty postupne. Potom tieto hodnoty namapujeme na požadovaný výstup.

Začnime našu aplikáciu a vyskúšajme ju potom prehliadaním koncového bodu.

Uvidíme, ako prehliadač zareaguje na udalosti, ktoré server posúva sekundu po sekunde. Pre viac informácií o Flux a Jadro reaktora, môžeme si pozrieť tento príspevok.

2.2. Využívanie ServerSentEvent Element

Teraz zabalíme náš výstup String do a ServerSentSevent objekt a preskúmať výhody tohto postupu:

@GetMapping ("/ stream-sse") verejný tok streamEvents () {return Flux.interval (Duration.ofSeconds (1)) .map (sequence -> ServerSentEvent. builder () .id (String.valueOf (sequence)) .event ("periodic-event") .data (" SSE - "+ LocalTime.now (). ToString ()) .build ()); }

Ako môžeme oceniť, Existuje niekoľko výhod používania ServerSentEvent subjekt:

  1. môžeme spracovať metadáta udalostí, ktoré by sme potrebovali v reálnom prípade
  2. môžeme ignorovať “text / stream udalostí”Deklarácia typu média

V tomto prípade sme zadali znak id, an názov udalosti, a čo je najdôležitejšie, skutočné údaje udalosti.

Mohli sme tiež pridať a komentáre atribút a a skúsiť znova hodnota, ktorá určí čas opätovného pripojenia, ktorý sa má použiť pri pokuse o odoslanie udalosti.

2.3. Spotrebovanie udalostí odoslaných serverom pomocou webového klienta

Teraz spotrebujme náš prúd udalostí s a Webový klient.:

public void consumeServerSentEvent () {WebClient client = WebClient.create ("// localhost: 8080 / sse-server"); ParameterizedTypeReference type = new ParameterizedTypeReference() {}; Flux eventStream = client.get () .uri ("/ stream-sse") .retrieve () .bodyToFlux (typ); eventStream.subscribe (content -> logger.info ("Time: {} - event: name [{}], id [{}], content [{}]", LocalTime.now (), content.event (), content.id (), content.data ()), chyba -> logger.error ("Chyba pri prijímaní SSE: {}", chyba), () -> logger.info ("Dokončené !!!")); }

The prihlásiť sa na odber Táto metóda umožňuje určiť, ako budeme postupovať, keď úspešne prijmeme udalosť, dôjde k chybe a keď je streamovanie dokončené.

V našom príklade sme použili načítať metóda, ktorá je jednoduchým a priamym spôsobom získania tela odpovede.

Táto metóda automaticky vyvolá a WebClientResponseException ak dostaneme odpoveď 4xx alebo 5xx, pokiaľ nespracujeme scenáre pridania súboru onStatus vyhlásenie.

Na druhej strane sme mohli použiť výmena metóda, ktorá poskytuje prístup k ClientResponse a tiež nevykazuje chybový signál pri zlyhaní odpovede.

Musíme stále brať do úvahy, že môžeme obísť ServerSentEvent wrapper, ak nepotrebujeme metadáta udalosti.

3. Streamovanie SSE na jar MVC

Ako sme už povedali, špecifikácia SSE bola podporovaná od jari 4.2, keď SseEmitter triedy bola zavedená.

Zjednodušene definujeme ExecutorService, vlákno, kde SseEmitter urobí svoju prácu tlačením údajov a vráti inštanciu emitoru, pričom udržiava spojenie otvorené týmto spôsobom:

@GetMapping ("/ stream-sse-mvc") verejné SseEmitter streamSseMvc () {SseEmitter emitter = nový SseEmitter (); ExecutorService sseMvcExecutor = Executors.newSingleThreadExecutor (); sseMvcExecutor.execute (() -> {try {for (int i = 0; true; i ++) {SseEventBuilder event = SseEmitter.event () .data ("SSE MVC -" + LocalTime.now (). toString ()) .id (String.valueOf (i)) .name ("sse event - mvc"); emitter.send (event); Thread.sleep (1000);}} catch (Exception ex) {emitter.completeWithError (ex); }}); spätný žiarič; }

Vždy vyberajte správne ExecutorService pre váš scenár prípadu použitia.

Môžeme sa dozvedieť viac o SSE na jar MVC a pozrieť sa na ďalšie príklady prečítaním tohto zaujímavého tutoriálu.

4. Porozumenie udalostiam odoslaných serverom

Teraz, keď vieme, ako implementovať koncové body SSE, skúsme ísť trochu hlbšie pochopením niektorých základných pojmov.

SSE je špecifikácia prijatá väčšinou prehľadávačov, ktorá umožňuje kedykoľvek jednosmerne streamovať udalosti.

„Udalosti“ sú iba prúdom textových údajov kódovaných UTF-8, ktoré sa riadia formátom definovaným v špecifikácii.

Tento formát pozostáva zo série prvkov kľúč - hodnota (id, retry, data a event, ktoré označujú názov) oddelených zalomením riadkov.

Podporované sú tiež komentáre.

Špecifikácia nijako neobmedzuje formát dátovej časti dát; môžeme použiť jednoduchý String alebo zložitejšia štruktúra JSON alebo XML.

Posledným bodom, ktorý musíme vziať do úvahy, je rozdiel medzi používaním streamovania SSE a Webové zásuvky.

Zatiaľ čo Webové zásuvky ponúkajú plne duplexnú (obojsmernú) komunikáciu medzi serverom a klientom, zatiaľ čo SSE využíva jednosmernú komunikáciu.

Tiež Webové zásuvky nie je protokolom HTTP a na rozdiel od SSE neponúka štandardy spracovania chýb.

5. Záver

Ak to zhrnieme, v tomto článku sme sa naučili hlavné koncepty streamovania SSE, čo je nepochybne skvelý zdroj, ktorý nám umožní vytvárať systémy novej generácie.

Teraz máme vynikajúcu pozíciu na to, aby sme pochopili, čo sa deje pod kapotou, keď používame tento protokol.

Ďalej sme teóriu doplnili niekoľkými jednoduchými príkladmi, ktoré nájdete v našom úložisku Github.


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