Útmutató a WebSocket Java API-jához

1. Áttekintés

A WebSocket alternatívát kínál a szerver és a webböngésző közötti hatékony kommunikáció korlátozására azáltal, hogy kétirányú, teljes duplex, valós idejű kliens / szerver kommunikációt biztosít. A szerver bármikor küldhet adatokat az ügyfélnek. Mivel TCP-n fut, alacsony késleltetésű, alacsony szintű kommunikációt is biztosít, és csökkenti az egyes üzenetek általános költségeit.

Ebben a cikkben egy csevegésszerű alkalmazás létrehozásával vesszük szemügyre a Java API for WebSockets alkalmazást.

2. JSR 356

A JSR 356 vagy a Java API for WebSocket meghatározza azt az API-t, amelyet a Java fejlesztők használhatnak a WebSocket integrálásához az alkalmazásokkal - mind a szerver, mind a Java kliens oldalon.

Ez a Java API a kiszolgáló és az ügyfél oldali összetevőket egyaránt biztosítja:

  • szerver: minden a javax.websocket.server csomag.
  • Ügyfél: tartalma javax.websocket csomag, amely kliens oldali API-kból, valamint a kiszolgáló és az ügyfél közös könyvtáraiból áll.

3. Csevegés készítése a WebSockets segítségével

Felépítünk egy nagyon egyszerű csevegésszerű alkalmazást. Bármely felhasználó bármely böngészőből megnyithatja a csevegést, beírhatja a nevét, bejelentkezhet a csevegésbe, és elkezdhet kommunikálni a csevegéssel kapcsolatban álló mindenkivel.

Kezdjük azzal, hogy hozzáadjuk a legfrissebb függőséget a pom.xml fájl:

 javax.websocket javax.websocket-api 1.1 

A legfrissebb verzió itt található.

A Java konvertálása érdekében Tárgyak a JSON reprezentációikba és fordítva, a Gson-t fogjuk használni:

 com.google.code.gson gson 2.8.0 

A legújabb verzió a Maven Central adattárban érhető el.

3.1. Végpont konfigurálása

Kétféle módon lehet konfigurálni a végpontokat: kommentár-alapú és kiterjesztés-alapú. Vagy meghosszabbíthatja a javax.websocket.Endpoint osztály, vagy használjon dedikált módszer-szintű kommentárokat. Mivel az annotációs modell tisztább kódhoz vezet, mint az automatizált modell, az annotáció a kódolás hagyományos választásává vált. Ebben az esetben a WebSocket végpont életciklus eseményeit a következő kommentárok kezelik:

  • @ServerEndpoint: Ha díszítik @ServerEndpoint, a konténer biztosítja az osztály elérhetőségét a WebSocket szerver egy adott URI helyet hallgat
  • @ClientEndpoint: Az ezzel az annotációval díszített osztályt a WebSocket ügyfél
  • @OnOpen: Java módszer a @OnOpen hívja meg a tároló, amikor egy új WebSocket kapcsolat indul
  • @OnMessage: Java metódus, azzal kiegészítve @OnMessage, megkapja az információt a WebSocket tároló, amikor üzenetet küld a végpontnak
  • @OnError: Egy módszer a @OnError akkor hívják meg, ha probléma van a kommunikációval
  • @OnClose: Egy Java módszer díszítésére szolgál, amelyet a tároló hív meg, amikor a WebSocket a kapcsolat bezárul

3.2. A kiszolgáló végpontjának megírása

Java osztályt deklarálunk WebSocket kiszolgáló végpontot azzal, hogy annotálja @ServerEndpoint. Meghatározzuk azt az URI-t is, ahová a végpont telepítve van. Az URI a kiszolgálótároló gyökeréhez viszonyítva van meghatározva, és egy perjelnek kell kezdődnie:

@ServerEndpoint (value = "/ chat / {felhasználónév}") public class ChatEndpoint {@OnOpen public void onOpen (Session session) dobja az IOException {// Munkamenet és WebSocket kapcsolat beolvasása} @OnMessage public void onMessage (Munkamenet, Üzenetüzenet) dobja az IOException-t {// Új üzenetek kezelése} @OnClose public void onClose (Session session) dobja az IOException-t {// WebSocket kapcsolat bezárul} @OnError public void onError (Session session, Throwable dobható) {// Hibakezelés itt}

A fenti kód a csevegésszerű alkalmazás szerver végpontjának csontváza. Mint láthatja, négy annotáció van feltérképezve a megfelelő módszereikkel. Az alábbiakban láthatja az ilyen módszerek megvalósítását:

@ServerEndpoint (value = "/ chat / {felhasználónév}") nyilvános osztály ChatEndpoint {privát munkamenet munkamenet; privát statikus Set chatEndpoints = new CopyOnWriteArraySet (); privát statikus HashMap felhasználók = új HashMap (); @OnOpen public void onOpen (Munkamenet, @PathParam ("felhasználónév") String felhasználónév) dobja az IOException {this.session = session; chatEndpoints.add (ez); users.put (session.getId (), felhasználónév); Üzenetüzenet = új Üzenet (); message.setFrom (felhasználónév); message.setContent ("Csatlakoztatva!"); adásüzenet); } @OnMessage public void onMessage (Munkamenet, Üzenetüzenet) dobja az IOException {message.setFrom (users.get (session.getId ())); adásüzenet); } @OnClose public void onClose (Session session) dobja az IOException {chatEndpoints.remove (ezt); Üzenetüzenet = új Üzenet (); message.setFrom (users.get (session.getId ())); message.setContent ("Bontott!"); adásüzenet); } @OnError public void onError (Session session, Throwable dobható) {// Itt hibakezelést végezhetünk} private static void broadcast (Message message) dobja az IOException, EncodeException {chatEndpoints.forEach (végpont -> {szinkronizált (végpont) {try {végpont .session.getBasicRemote (). sendObject (message);} catch (IOException | EncodeException e) {e.printStackTrace ();}}}); }}

Amikor egy új felhasználó bejelentkezik (@OnOpen) azonnal hozzárendelésre kerül az aktív felhasználók adatstruktúrájához. Ezután egy üzenet jön létre, és elküldik az összes végpontnak a adás módszer.

Ezt a módszert akkor is használják, amikor új üzenetet küldenek (@OnMessage) bármelyik csatlakoztatott felhasználó által - ez a csevegés fő célja.

Ha valamikor hiba lép fel, akkor a módszer az annotációval együtt @OnError kezeli. Ezzel a módszerrel naplózhatja a hibával kapcsolatos információkat és törölheti a végpontokat.

Végül, ha egy felhasználó már nincs csatlakoztatva a csevegéshez, a módszer @OnClose törli a végpontot, és minden felhasználó számára elküldi, hogy a felhasználó megszakadt.

4. Üzenettípusok

A WebSocket specifikáció két vezetékes adatformátumot támogat - szöveges és bináris. Az API támogatja ezeket a formátumokat, hozzáadja a Java objektumokkal és állapotfelmérési üzenetekkel (ping-pong) való együttműködés képességeit a specifikációban meghatározottak szerint:

  • Szöveg: Bármely szöveges adat (java.lang.String, primitívek vagy ezeknek megfelelő burkolóosztályok)
  • Bináris: Bináris adatok (pl. Hang, kép stb.), Amelyet a java.nio.ByteBuffer vagy a byte[] (bájt tömb)
  • Java objektumok: Az API lehetővé teszi a natív (Java objektum) reprezentációk használatát a kódban, és egyedi transzformátorok (kódolók / dekóderek) használatával konvertálhatja azokat a WebSocket protokoll által engedélyezett kompatibilis vezetékes formátumokra (szöveges, bináris).
  • Ping pong: A javax.websocket.PongMessage egy nyugtázás, amelyet egy WebSocket-partner küldött meg állapotfelmérési (ping) kérelemre válaszul

Alkalmazásunkhoz használni fogjuk Java objektumok. Hozunk létre osztályokat az üzenetek kódolásához és dekódolásához.

4.1. Encoder

A kódoló Java objektumot vesz fel, és tipikus ábrázolást készít, amely üzenetként továbbítható, például JSON, XML vagy bináris ábrázolás. A kódolókat a Encoder.Text vagy Encoder.Binary interfészek.

Az alábbi kódban meghatározzuk az osztályt Üzenet kódolni és a módszerben kódol a Gson-t használjuk a Java objektum JSON-ba történő kódolásához:

public class Üzenet {private String from; privát String to; privát String tartalom; // szabványos kivitelezők, mérőeszközök, beállítók}
public class MessageEncoder implementálja az Encoder.Text {private static Gson gson = new Gson (); @Orride public String encode (Message message) dobja az EncodeException {return gson.toJson (üzenet); } @Orride public void init (EndpointConfig endpointConfig) {// Egyéni inicializálási logika} @Orride public void destr (() {// Források bezárása}}

4.2. Dekóder

A dekóder ellentéte a kódolónak, és arra használják, hogy az adatokat visszaalakítsák Java objektummá. A dekódereket a Dekóder. Szöveg vagy Dekóder.Bináris interfészek.

Ahogy a kódolóval láttuk, a dekódolni A módszer az, amikor a végpontnak küldött üzenetben lekérjük a JSON-t, és a Gson segítségével átalakítjuk egy úgynevezett Java osztályba. Üzenet:

public class MessageDecoder implementálja a Decoder.Text {private static Gson gson = new Gson (); @Orride public Message decode (String s) dobja a DecodeException {return gson.fromJson (s, Message.class); } @Orride public boolean willDecode (String s) {return (s! = Null); } @Orride public void init (EndpointConfig endpointConfig) {// Egyéni inicializálási logika} @Orride public void destr (() {// Források bezárása}}

4.3. Kódoló és dekóder beállítása a kiszolgáló végpontjában

Tegyük össze mindent úgy, hogy az adatok kódolásához és dekódolásához létrehozott osztályokat hozzáadjuk az osztály szintű kommentárhoz @ServerEndpoint:

@ServerEndpoint (érték = "/ chat / {felhasználónév}", dekóderek = MessageDecoder.class, kódolók = MessageEncoder.class)

Minden alkalommal, amikor az üzeneteket elküldik a végpontnak, automatikusan átalakulnak JSON vagy Java objektumokká.

5. Következtetés

Ebben a cikkben megvizsgáltuk, mi a Java API a WebSockets számára, és hogyan segíthet nekünk olyan alkalmazások felépítésében, mint ez a valós idejű csevegés.

Láttuk a végpont létrehozásának két programozási modelljét: annotációkat és programokat. Meghatároztunk egy végpontot az alkalmazásunkhoz tartozó annotációs modell felhasználásával, az életciklus-módszerekkel együtt.

A kiszolgáló és az ügyfél közötti oda-vissza kommunikációhoz azt is láttuk, hogy kódolókra és dekóderekre van szükségünk a Java objektumok JSON-vá és fordítva konvertálására.

A JSR 356 API nagyon egyszerű, és az annotáció alapú programozási modell nagyon egyszerűvé teszi a WebSocket alkalmazások felépítését.

A példában épített alkalmazás futtatásához mindössze annyit kell tennünk, hogy telepítjük a háborús fájlt egy webszerverre, és elmegyünk az URL-re: // localhost: 8080 / java-websocket /. A lerakat linkjét itt találja.