程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> JavaEE7+Websockets+GlassFish4打造聊天室

JavaEE7+Websockets+GlassFish4打造聊天室

編輯:關於JAVA

JavaEE7+Websockets+GlassFish4打造聊天室。本站提示廣大學習愛好者:(JavaEE7+Websockets+GlassFish4打造聊天室)文章只能為提供參考,不一定能成為您想要的結果。以下是JavaEE7+Websockets+GlassFish4打造聊天室正文


在客戶機和辦事器之間樹立單一的雙向銜接,這就意味著客戶只須要發送一個要求到辦事端,那末辦事端則會停止處置,處置好後則將其前往給客戶端,客戶端則可以在期待這個時光持續去做其他任務,全部進程是異步的。在本系列教程中,將指點用戶若何在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" /> 
     <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完成的聊天室,願望對年夜家的進修有所贊助。

nt.getRoundX(),lyjCirclePoint.getRoundY(), lyjCirclePoint.getRadiu(),circlePaint); } } //繪制用bitmap創立出來的畫布 @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(bitmap, 0, 0, null); } }

如許便可以獲得以下界面後果(固然反編譯百度錢包,並沒有百度錢包中的圖片,只好隨意找了一張圖片):

以上就是本文的全體內容,願望對年夜家進修Android有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved