亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

JavaEE7+Websockets+GlassFish4打造聊天室

2019-11-26 14:58:53
字體:
來源:轉載
供稿:網友

在客戶機和服務器之間建立單一的雙向連接,這就意味著客戶只需要發送一個請求到服務端,那么服務端則會進行處理,處理好后則將其返回給客戶端,客戶端則可以在等待這個時間繼續去做其他工作,整個過程是異步的。在本系列教程中,將指導用戶如何在JAVA EE 7的容器GlassFish 4中,使用JAVA EE 7中的全新的解析Json API(JSR-353),以及綜合運用jQuery和Bootstrap。本文要求讀者有一定的HTML 5 Websocket的基礎原理知識。

效果圖

我們先來看下在完成這個教程后的效果圖,如下所示:

準備工作

我們使用的是JDK 7 和MAVN 3進行庫的構建工作,首先看pom.xml中關于Jave EE 7的部分:

 <properties>  <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>  <dependencies>  <dependency>   <groupId>javax</groupId>   <artifactId>javaee-api</artifactId>   <version>7.0</version>   <scope>provided</scope>  </dependency> </dependencies>  <build>  <plugins>   <plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-compiler-plugin</artifactId>    <version>3.1</version>    <configuration>     <source>1.7</source>     <target>1.7</target>     <compilerArguments>      <endorseddirs>${endorsed.dir}</endorseddirs>     </compilerArguments>    </configuration>   </plugin>   <plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-war-plugin</artifactId>    <version>2.3</version>    <configuration>     <failOnMissingWebXml>false</failOnMissingWebXml>    </configuration>   </plugin>   <plugin>    <groupId>org.apache.maven.plugins</groupId>    <artifactId>maven-dependency-plugin</artifactId>    <version>2.6</version>    [..]   </plugin>  </plugins> </build> 

同時,為了能使用GlassFish 4,需要增加如下的插件:

plugin>  <groupId>org.glassfish.embedded</groupId>  <artifactId>maven-embedded-glassfish-plugin</artifactId>  <version>4.0</version>  <configuration>   <goalPrefix>embedded-glassfish</goalPrefix>   <app>${basedir}/target/${project.artifactId}-${project.version}.war</app>   <autoDelete>true</autoDelete>   <port>8080</port>   <name>${project.artifactId}</name>   <contextRoot>hascode</contextRoot>  </configuration>  <executions>   <execution>    <goals>     <goal>deploy</goal>    </goals>   </execution>  </executions> </plugin> 

設置Websocket的Endpoint

我們先來看服務端Websocket的代碼如下,然后再做進一步解析:

package com.hascode.tutorial;  import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger;  import javax.websocket.EncodeException; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint;  @ServerEndpoint(value = "/chat/{room}", encoders = ChatMessageEncoder.class, decoders = ChatMessageDecoder.class) public class ChatEndpoint {  private final Logger log = Logger.getLogger(getClass().getName());   @OnOpen  public void open(final Session session, @PathParam("room") final String room) {   log.info("session openend and bound to room: " + room);   session.getUserProperties().put("room", room);  }   @OnMessage  public void onMessage(final Session session, final ChatMessage chatMessage) {   String room = (String) session.getUserProperties().get("room");   try {    for (Session s : session.getOpenSessions()) {     if (s.isOpen()       && room.equals(s.getUserProperties().get("room"))) {      s.getBasicRemote().sendObject(chatMessage);     }    }   } catch (IOException | EncodeException e) {    log.log(Level.WARNING, "onMessage failed", e);   }  } } 

下面分析下上面的代碼:

使用@ ServerEndpoint定義一個新的endpoint,其中的值指定了URL并且可以使用PathParams參數,就象在JAX-RS中的用法一樣。

所以值“/chat/{room}”允許用戶通過如下形式的URL去連接某個聊天室:ws://0.0.0.0:8080/hascode/chat/java

在大括號中的值(即room),可以通過使用javax.websocket.server.PathParam,在endpoint的生命周期回調方法中以參數的方式注入。

此外,我們要使用一個編碼和解碼的類,因為我們使用的是一個DTO形式的類,用于在服務端和客戶端傳送數據。

當用戶第一次連接到服務端,輸入要進入聊天室的房號,則這個房號以參數的方式注入提交,并且使用session.getUserProperties將值保存在用戶的屬性map中。

當一個聊天參與者通過tcp連接發送信息到服務端,則循環遍歷所有已打開的session,每個session被綁定到指定的聊天室中,并且接收編碼和解碼的信息。

如果我們想發送簡單的文本信息或和二進制格式的信息,則可以使用session.getBasicRemote().sendBinary() 或session.getBasicRemote().sendText()

接下來我們看下用于代表信息傳遞實體(DTO:Data Transfer Object)的代碼,如下:

package com.hascode.tutorial;  import java.util.Date;  public class ChatMessage {  private String message;  private String sender;  private Date received;   // 其他getter,setter方法 } 

聊天消息的轉換

在這個應用中,將編寫一個編碼和解碼類,用于在聊天信息和JSON格式間進行轉換。

先來看下解碼類的實現,這將會把傳遞到服務端的聊天信息轉換為ChatMessage實體類。在這里,使用的是Java API for JSON Processing(JSR353)規范去將JSON格式的信息轉換為實體類,代碼如下,其中重寫的willDecode方法,這里默認返回為true。

package com.hascode.tutorial;  import java.io.StringReader; import java.util.Date;  import javax.json.Json; import javax.json.JsonObject; import javax.websocket.DecodeException; import javax.websocket.Decoder; import javax.websocket.EndpointConfig;  public class ChatMessageDecoder implements Decoder.Text<ChatMessage> {  @Override  public void init(final EndpointConfig config) {  }   @Override  public void destroy() {  }   @Override  public ChatMessage decode(final String textMessage) throws DecodeException {   ChatMessage chatMessage = new ChatMessage();   JsonObject obj = Json.createReader(new StringReader(textMessage))     .readObject();   chatMessage.setMessage(obj.getString("message"));   chatMessage.setSender(obj.getString("sender"));   chatMessage.setReceived(new Date());   return chatMessage;  }   @Override  public boolean willDecode(final String s) {   return true;  } } 

同樣再看下編碼類的代碼,這個類相反,是將ChatMessage類轉換為Json格式,代碼如下:

package com.hascode.tutorial;  import javax.json.Json; import javax.websocket.EncodeException; import javax.websocket.Encoder; import javax.websocket.EndpointConfig;  public class ChatMessageEncoder implements Encoder.Text<ChatMessage> {  @Override  public void init(final EndpointConfig config) {  }   @Override  public void destroy() {  }   @Override  public String encode(final ChatMessage chatMessage) throws EncodeException {   return Json.createObjectBuilder()     .add("message", chatMessage.getMessage())     .add("sender", chatMessage.getSender())     .add("received", chatMessage.getReceived().toString()).build()     .toString();  } } 

這里可以看到JSR-353的強大威力,只需要調用Json.createObjectBuilder就可以輕易把一個DTO對象轉化為JSON了。

通過Bootstrap、Javacsript搭建簡易客戶端

最后,我們綜合運用著名的Bootstrap、jQuery框架和Javascript設計一個簡易的客戶端。我們在src/main/weapp目錄下新建立index.html文件,代碼如下:

<!DOCTYPE html> <html lang="en"> <head> [..] <script>  var wsocket;  var serviceLocation = "ws://0.0.0.0:8080/hascode/chat/";  var $nickName;  var $message;  var $chatWindow;  var room = '';   function onMessageReceived(evt) {   //var msg = eval('(' + evt.data + ')');   var msg = JSON.parse(evt.data); // native API   var $messageLine = $('<tr><td class="received">' + msg.received     + '</td><td class="user label label-info">' + msg.sender     + '</td><td class="message badge">' + msg.message     + '</td></tr>');   $chatWindow.append($messageLine);  }  function sendMessage() {   var msg = '{"message":"' + $message.val() + '", "sender":"'     + $nickName.val() + '", "received":""}';   wsocket.send(msg);   $message.val('').focus();  }   function connectToChatserver() {   room = $('#chatroom option:selected').val();   wsocket = new WebSocket(serviceLocation + room);   wsocket.onmessage = onMessageReceived;  }   function leaveRoom() {   wsocket.close();   $chatWindow.empty();   $('.chat-wrapper').hide();   $('.chat-signin').show();   $nickName.focus();  }   $(document).ready(function() {   $nickName = $('#nickname');   $message = $('#message');   $chatWindow = $('#response');   $('.chat-wrapper').hide();   $nickName.focus();    $('#enterRoom').click(function(evt) {    evt.preventDefault();    connectToChatserver();    $('.chat-wrapper h2').text('Chat # '+$nickName.val() + "@" + room);    $('.chat-signin').hide();    $('.chat-wrapper').show();    $message.focus();   });   $('#do-chat').submit(function(evt) {    evt.preventDefault();    sendMessage()   });    $('#leave-room').click(function(){    leaveRoom();   });  }); </script> </head>  <body>   <div class="container chat-signin">   <form class="form-signin">    <h2 class="form-signin-heading">Chat sign in</h2>    <label for="nickname">Nickname</label> <input type="text"     class="input-block-level" placeholder="Nickname" id="nickname">    <div class="btn-group">     <label for="chatroom">Chatroom</label> <select size="1"      id="chatroom">      <option>arduino</option>      <option>java</option>      <option>groovy</option>      <option>scala</option>     </select>    </div>    <button class="btn btn-large btn-primary" type="submit"     id="enterRoom">Sign in</button>   </form>  </div>  <!-- /container -->   <div class="container chat-wrapper">   <form id="do-chat">    <h2 class="alert alert-success"></h2>    <table id="response" class="table table-bordered"></table>    <fieldset>     <legend>Enter your message..</legend>     <div class="controls">      <input type="text" class="input-block-level" placeholder="Your message..." id="message" style="height:60px"/>      <input type="submit" class="btn btn-large btn-block btn-primary"       value="Send message" />      <button class="btn btn-large btn-block" type="button" id="leave-room">Leave       room</button>     </div>    </fieldset>   </form>  </div> </body> </html> 

在上面的代碼中,要注意如下幾點:

在Javascript端要調用websocket的話,要用如下的方式發起連接即可:ws://IP:PORT/CONTEXT_PATH/ENDPOINT_URL e.g ws://0.0.0.0:8080/hascode/chat/java

創建一個Websocket連接的方法很簡單,使用的是var wsocket = new WebSocket(‘ws://0.0.0.0:8080/hascode/chat/java');

要獲得來自服務端返回的信息,只需要在回調函數wsocket.onmessage中設置對應的獲取返回信息的方法即可。

發送一個Websocket消息到服務端,使用的方法是wsocket.send(),其中可以發送的消息可以文本或者二進制數據。

關閉連接使用的是wsocket.close()。

最后,我們通過mvn package embedded-glassfish:run進行代碼的部署,然后就可以看到本文開始部分截圖的效果。

以上就是用JavaEE7、Websockets和GlassFish4實現的聊天室,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美专区中文字幕| 中文字幕免费精品一区高清| 亚洲天堂网站在线观看视频| 免费av在线一区| 国产欧美日韩亚洲精品| 亚洲精品美女久久| 怡红院精品视频| 国产精品第七十二页| 国产精品视频自在线| 久久精品99久久久久久久久| 日韩精品亚洲精品| 国产在线观看精品一区二区三区| 91高清在线免费观看| 日韩精品视频免费专区在线播放| 日本久久91av| 日韩一级黄色av| 不用播放器成人网| 国产精品欧美一区二区| 久久久精品中文字幕| 欧美成人免费在线观看| 亚洲福利视频免费观看| 粗暴蹂躏中文一区二区三区| 成人av.网址在线网站| 久久久精品美女| 国产手机视频精品| 久久久久久久久爱| 欧美俄罗斯性视频| 久久免费成人精品视频| 日韩精品福利在线| 成人美女免费网站视频| 97视频免费在线观看| 国产日韩欧美夫妻视频在线观看| 久久久久久久久久久av| 亚洲成色777777女色窝| 欧美性猛交xxxx免费看久久久| 日韩在线观看你懂的| 日韩www在线| 国产精品偷伦免费视频观看的| 久久成人免费视频| 777午夜精品福利在线观看| 91成人在线观看国产| 精品欧美aⅴ在线网站| 亚洲色图在线观看| 成人h猎奇视频网站| 色先锋久久影院av| 亚洲免费人成在线视频观看| 992tv成人免费影院| 日韩一级裸体免费视频| 久久久www成人免费精品| 久久久爽爽爽美女图片| 久久久精品国产网站| 国产亚洲精品成人av久久ww| 久久免费精品视频| 综合网中文字幕| 国产国语刺激对白av不卡| 国产中文字幕91| 2019中文字幕在线免费观看| 国产精品1区2区在线观看| 日韩av电影国产| 亚洲精品资源美女情侣酒店| 国内精品久久久久久影视8| 亚洲sss综合天堂久久| 欧美成人一区二区三区电影| 日韩视频在线一区| 欧美黄色片免费观看| 欧美疯狂做受xxxx高潮| 国内精品一区二区三区| 91精品国产91久久久久| 亚洲在线免费视频| 国内精品400部情侣激情| 国产视频久久久| 国产精品毛片a∨一区二区三区|国| 在线播放国产一区二区三区| www.日本久久久久com.| 国产在线拍揄自揄视频不卡99| 亚洲无av在线中文字幕| 欧美极品第一页| 日韩精品在线私人| 国产成人综合一区二区三区| 日韩激情第一页| 91tv亚洲精品香蕉国产一区7ujn| 亚洲福利视频网| 这里只有精品久久| 中文字幕免费精品一区高清| 亚洲xxxx在线| 久久久电影免费观看完整版| 奇米成人av国产一区二区三区| 亚洲人午夜精品免费| 亚洲成色777777在线观看影院| 91成人在线视频| www.亚洲天堂| 国产一区二区三区三区在线观看| 影音先锋欧美在线资源| 91精品国产综合久久久久久蜜臀| 欧美午夜激情在线| 日韩福利视频在线观看| 日韩一区二区在线视频| 久久色在线播放| 色综合久久精品亚洲国产| 成人日韩av在线| 亚洲最大在线视频| 清纯唯美亚洲综合| 国产日韩在线视频| 国产成人精品999| 日本精品久久久久影院| 国产一区二区三区丝袜| 中文字幕综合在线| 亚洲国产高清高潮精品美女| 成人高h视频在线| 欧美日韩国产一中文字不卡| 一级做a爰片久久毛片美女图片| 97精品国产aⅴ7777| 精品国产电影一区| 欧美午夜精品久久久久久久| 在线观看日韩av| 欧美性xxxx极品高清hd直播| 日韩美女av在线| 亚洲欧美在线磁力| 日韩av网站电影| 国产精品欧美一区二区三区奶水| 国产一区二区日韩精品欧美精品| 亚洲天天在线日亚洲洲精| 日韩中文理论片| 久久久久亚洲精品成人网小说| 国产91九色视频| 国产精品吊钟奶在线| 国产精品成人一区二区| 精品国产乱码久久久久久婷婷| 国产精品视频成人| 91av视频在线观看| 亚洲欧美综合精品久久成人| 色妞在线综合亚洲欧美| 最近中文字幕2019免费| 久久久久久久久久久av| 欧美性黄网官网| 欧美精品videossex88| 亚洲精品二三区| 国产日韩精品在线| 日韩**中文字幕毛片| 8x海外华人永久免费日韩内陆视频| 亚洲精品国产精品国产自| 国产精品综合网站| 久久免费高清视频| 欧美成人精品影院| 欧美激情中文字幕乱码免费| 国产美女久久久| 萌白酱国产一区二区| 91精品综合久久久久久五月天| 日本国产高清不卡| 国产在线久久久| 亚洲欧洲在线播放| 精品国产精品三级精品av网址| 国产精品网站视频| 日韩欧美在线观看| 亚洲tv在线观看| 欧美性xxxxhd| 国产精品免费电影| 亚洲免费av片| 亚洲国产天堂久久综合网| 97人人模人人爽人人喊中文字| 成人精品视频久久久久| 亚洲肉体裸体xxxx137| 欧美激情综合亚洲一二区| 亚洲精品一区二区久|