מדריך ל- API של Java עבור WebSocket

1. סקירה כללית

WebSocket מספק חלופה למגבלת התקשורת היעילה בין השרת לדפדפן האינטרנט על ידי מתן תקשורת לקוח / שרת דו-כיוונית, דו-צדדית, בזמן אמת. השרת יכול לשלוח נתונים ללקוח בכל עת. מכיוון שהוא פועל באמצעות TCP, הוא גם מספק תקשורת ברמה נמוכה עם זמן אחזור ומפחית את התקורה של כל הודעה.

במאמר זה נסתכל על Java API עבור WebSockets על ידי יצירת יישום דמוי צ'אט.

2. JSR 356

JSR 356 או Java API for WebSocket, מציין ממשק API שמפתחי Java יכולים להשתמש בו לשילוב WebSockets עם היישומים שלהם - הן בצד השרת והן בצד לקוח Java.

ממשק API זה של Java מספק רכיבים בצד השרת וגם בצד הלקוח:

  • שרת: הכל ב javax.websocket.server חֲבִילָה.
  • לָקוּחַ: התוכן של javax.websocket חבילה, המורכבת מממשקי API של צד הלקוח וגם מספריות נפוצות לשרת ולקוח.

3. בניית צ'אט באמצעות WebSockets

נבנה יישום פשוט מאוד דמוי צ'אט. כל משתמש יוכל לפתוח את הצ'אט מכל דפדפן, להקליד את שמו, להתחבר לצ'אט ולהתחיל לתקשר עם כל מי שמחובר לצ'אט.

נתחיל בהוספת התלות האחרונה ל- pom.xml קוֹבֶץ:

 javax.websocket javax.websocket-api 1.1 

הגרסה האחרונה תוכל למצוא כאן.

על מנת להמיר ג'אווה חפצים בייצוגי JSON שלהם ולהיפך, נשתמש ב- Gson:

 com.google.code.gson gson 2.8.0 

הגרסה האחרונה זמינה במאגר Maven Central.

3.1. תצורת נקודות קצה

ישנן שתי דרכים להגדרת נקודות קצה: ביאור-מבוסס ותוספות. אתה יכול להאריך את javax.websocket.Endpoint מחלק או השתמש בהערות ייעודיות ברמת השיטה. מכיוון שמודל ההערות מוביל לקוד נקי יותר בהשוואה למודל הפרוגרמטי, ההערה הפכה לבחירה המקובלת של קידוד. במקרה זה, אירועי מחזור חיים של נקודות קצה של WebSocket מטופלים על ידי ההערות הבאות:

  • @ ServerEndpoint: אם מעוטר ב @ ServerEndpoint, המכולה מבטיחה זמינות המחלקה כ- WebSocket שרת מאזין למרחב URI ספציפי
  • @ClientEndpoint: מתייחסים לכיתה המעוטרת בהערה זו כ- WebSocket לָקוּחַ
  • @OnOpen: שיטת Java עם @OnOpen מופעל על ידי המכולה כאשר חדש WebSocket החיבור יזם
  • @OnMessage: שיטת Java, עם הערות @OnMessage, מקבל את המידע מה- WebSocket מיכל כאשר הודעה נשלחת לנקודת הקצה
  • @OnError: שיטה עם @OnError מופעל כשיש בעיה בתקשורת
  • @OnClose: משמש לקישוט שיטת Java הנקראת על ידי המכולה כאשר ה- WebSocket החיבור נסגר

3.2. כתיבת נקודת הקצה של השרת

אנו מצהירים על כיתת Java WebSocket נקודת קצה של שרת על ידי הערת זה עם @ ServerEndpoint. אנו מציינים גם את ה- URI שבו נקודת הקצה נפרסת. ה- URI מוגדר יחסית לשורש של מיכל השרת ועליו להתחיל עם קו נטוי קדימה:

@ ServerEndpoint (value = "/ chat / {username}") class public ChatEndpoint {@OnOpen public void onOpen (session session) זורק IOException {// קבל מושב וחיבור WebSocket} @OnMessage public public ריק עלMessage (מושב מושב, הודעת הודעה) זורק IOException {// מטפל בהודעות חדשות} @OnClose בטל בציבור onClose (מושב מושב) זורק IOException {// חיבור WebSocket נסגר} @ OnError בטל בציבור onError (מושב מושב, זורק לזריקה) {// האם טיפול בשגיאות כאן}}

הקוד שלעיל הוא שלד נקודות הקצה של השרת ליישום דמוי הצ'אט שלנו. כפי שאתה יכול לראות, יש לנו 4 הערות הממופות לשיטות בהתאמה. להלן ניתן לראות את הטמעת שיטות כאלה:

@ ServerEndpoint (value = "/ chat / {username}") ChatEndpoint מחלקה ציבורית {מושב מושב פרטי; סט סטטי פרטי chatEndpoints = new CopyOnWriteArraySet (); משתמשי HashMap סטטיים פרטיים = HashMap חדש (); @OnOpen חלל ציבורי onOpen (מושב מושב, @PathParam ("שם משתמש") שם משתמש מחרוזת) זורק IOException {this.session = session; chatEndpoints.add (זה); users.put (session.getId (), שם משתמש); הודעת הודעה = הודעה חדשה (); message.setFrom (שם משתמש); message.setContent ("מחובר!"); הודעת שידור); } @OnMessage חלל ציבורי onMessage (מושב מושב, הודעת הודעה) זורק IOException {message.setFrom (users.get (session.getId ())); הודעת שידור); } @OnClose חלל ציבורי onClose (מושב מושב) זורק IOException {chatEndpoints.remove (this); הודעת הודעה = הודעה חדשה (); message.setFrom (users.get (session.getId ())); message.setContent ("מנותק!"); הודעת שידור); } @OnError בטל ציבורי onError (מושב מושב, זורק לזריקה) {// האם טיפול כאן בשגיאה} שידור ריק סטטי פרטי (הודעת הודעה) זורק IOException, EncodeException {chatEndpoints.forEach (נקודת קצה -> {מסונכרן (נקודת קצה) {נסה {endpoint .session.getBasicRemote (). sendObject (הודעה);} לתפוס (IOException | EncodeException e) {e.printStackTrace ();}}}); }}

כאשר משתמש חדש מתחבר (@OnOpen) ממופה מיד למבנה נתונים של משתמשים פעילים. לאחר מכן, נוצרת הודעה ונשלחת לכל נקודות הקצה באמצעות ה- מִשׁדָר שיטה.

שיטה זו משמשת גם בכל פעם שנשלחת הודעה חדשה (@OnMessage) על ידי כל אחד מהמשתמשים המחוברים - זו המטרה העיקרית של הצ'אט.

אם בשלב כלשהו מתרחשת שגיאה, השיטה עם ההערה @OnError מטפל בזה. באפשרותך להשתמש בשיטה זו כדי לרשום את המידע אודות השגיאה ולנקות את נקודות הקצה.

לבסוף, כאשר משתמש כבר לא מחובר לצ'אט, השיטה @OnClose מנקה את נקודת הקצה ומשדר לכל המשתמשים שמשתמש נותק.

4. סוגי הודעות

המפרט של WebSocket תומך בשני פורמטי נתונים ברשת - טקסט ובינארי. ה- API תומך בשני הפורמטים הללו, מוסיף יכולות לעבודה עם אובייקטים של Java והודעות בדיקת תקינות (פינג-פונג) כהגדרתן במפרט:

  • טֶקסט: כל נתונים טקסטואליים (מיתר, פרימיטיבים או שיעורי העטיפה המקבילים שלהם)
  • בינארי: נתונים בינאריים (למשל שמע, תמונה וכו ') המיוצגים על ידי a java.nio.ByteBuffer או א בתים [] (מערך בתים)
  • אובייקטים של Java: ה- API מאפשר לעבוד עם ייצוגים מקוריים (אובייקט Java) בקוד שלך ולהשתמש בשנאים מותאמים אישית (מקודדים / מפענחים) כדי להמיר אותם לפורמטים תואמים ברשת (טקסט, בינארי) המותרים על ידי פרוטוקול WebSocket
  • פינג פונג: א javax.websocket.PongMessage היא אישור שנשלח על ידי עמית WebSocket בתגובה לבקשת בדיקת בריאות (פינג)

עבור היישום שלנו, נשתמש אובייקטים של Java. ניצור את הכיתות לקידוד ופענוח הודעות.

4.1. קוֹדַאִי

מקודד לוקח אובייקט Java ומייצר ייצוג אופייני המתאים להעברה כהודעה כמו JSON, XML או ייצוג בינארי. ניתן להשתמש בקודנים על ידי יישום ה- מקודד. טקסט אוֹ מקודד. בינארי ממשקים.

בקוד שלמטה אנו מגדירים את הכיתה הוֹדָעָה להיות מקודד ובשיטה לְהַצְפִּין אנו משתמשים ב- Gson לקידוד אובייקט Java ל- JSON:

הודעה בכיתה ציבורית {פרטי מחרוזת מ; מחרוזת פרטית ל; תוכן מחרוזת פרטי; // בונים סטנדרטיים, גטרים, סטרים}
מחלקה ציבורית MessageEncoder מיישם את Encoder.Text {פרטי Gson gson gson = Gson new (); @Override ציבורי מחרוזת (הודעת הודעה) זורק EncodeException {להחזיר gson.toJson (הודעה); } @Override init void public (EndpointConfig endpointConfig) {// לוגיקה של אתחול מותאם אישית} @Override public void להשמיד () {// סגור משאבים}}

4.2. מפענח

מפענח הוא ההיפך מקודד ומשמש להמרת נתונים לאובייקט ג'אווה. ניתן ליישם מפענחים באמצעות ה- מפענח. טקסט אוֹ מפענח. בינארי ממשקים.

כפי שראינו עם המקודד, ה- לְפַעֲנֵחַ השיטה היא המקום בו אנו לוקחים את ה- JSON שאוחזר בהודעה שנשלחה לנקודת הקצה ומשתמש ב- Gson כדי להפוך אותו למחלקת Java הנקראת הוֹדָעָה:

מחלקה ציבורית MessageDecoder מיישם Decoder.Text {פרטי Gson gson gson = Gson new (); @ Override פענוח הודעות פומבי (מחרוזות) זורק DecodeException {להחזיר gson.fromJson (s, Message.class); } @Override willDecode בוליאני ציבורי (מחרוזות) {return (s! = Null); } @Override init void public (EndpointConfig endpointConfig) {// לוגיקה של אתחול מותאם אישית} @Override public void להשמיד () {// סגור משאבים}}

4.3. הגדרת מקודד ומפענח בנקודת קצה של השרת

בואו נרכיב את הכל על ידי הוספת המחלקות שנוצרו לקידוד ופענוח הנתונים בהערה ברמת הכיתה @ ServerEndpoint:

@ ServerEndpoint (value = "/ chat / {username}", מפענחים = MessageDecoder.class, מקודדים = MessageEncoder.class)

בכל פעם שנשלחות הודעות לנקודת הקצה, הן יומרו אוטומטית לאובייקטים JSON או Java.

5. מסקנה

במאמר זה בדקנו מהו ה- API של Java עבור WebSockets וכיצד הוא יכול לעזור לנו בבניית יישומים כגון צ'אט בזמן אמת זה.

ראינו את שני מודלי התכנות ליצירת נקודת קצה: ביאורים ותכנותיים. הגדרנו נקודת קצה באמצעות מודל ההערה ליישום שלנו יחד עם שיטות מחזור החיים.

כמו כן, על מנת שנוכל לתקשר הלוך ושוב בין השרת ללקוח, ראינו שאנחנו זקוקים לקודנים ומפענחים כדי להמיר אובייקטים של Java ל- JSON ולהיפך.

ה- API של JSR 356 הוא פשוט מאוד ומודל התכנות מבוסס ההערות שמקל מאוד על בניית יישומי WebSocket.

כדי להריץ את היישום שבנינו בדוגמה, כל שעלינו לעשות הוא לפרוס את קובץ המלחמה בשרת אינטרנט וללכת לכתובת ה- URL: // localhost: 8080 / java-websocket /. תוכלו למצוא את הקישור למאגר כאן.