Java中Websocket使用實例解析

Java中Websocket使用實例解析

日期:2023-03-09 16:36:55    编辑:网络投稿    来源:互联网

Java中Websocket使用實例解析  在 WebSocket API,瀏覽器和服務器只需要要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送

Java中Websocket使用實例解析

  在 WebSocket API,瀏覽器和服務器只需要要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。下面小編給大家介紹Java中Websocket使用實例解析,歡迎閱讀!

  Java中Websocket使用實例解析

  運行環境

  客戶端

  實現了websocket的瀏覽器



Chrome Supported in version 4+ Firefox Supported in version 4+ Internet Explorer Supported in version 10+ Opera Supported in version 10+ Safari Supported in version 5+

  服務端

  依賴

  <dependency>

  <groupId>org.apache.tomcat</groupId>

  <artifactId>tomcat-websocket-api</artifactId>

  <version>7.0.47</version>

  <scope>provided</scope>

  </dependency>

  <dependency>

  <groupId>javax</groupId>

  <artifactId>javaee-api</artifactId>

  <version>7.0</version>

  <scope>provided</scope>

  </dependency>

  注意:早前業界沒有統一的標準,各服務器都有各自的實現,現在J2EE7的JSR356已經定義了統一的標準,請盡量使用支持最新通用標準的服務器。

  我是用的Tomcat 7.0.57 + Java7

  必須是Tomcat 7.0.47以上

  ps:最早我們是用的Tomcat 7自帶的實現,后來要升級Tomcat 8,結果原來的實現方式在Tomcat 8不支持了,就只好切換到支持Websocket 1.0版本的Tomcat了。

  主流的java web服務器都有支持JSR365標準的版本了,請自行Google。

  用nginx做反向代理的需要注意啦,socket請求需要做特殊配置的,切記!

  Tomcat的處理方式建議修改為NIO的方式,同時修改連接數到合適的參數,請自行Google!

  服務端不需要在web.xml中做額外的配置,Tomcat啟動后就可以直接連接了。

  實現

  import com.dooioo.websocket.utils.SessionUtils;

  import org.apache.commons.logging.Log;

  import org.apache.commons.logging.LogFactory;

  import javax.websocket.*;

  import javax.websocket.server.PathParam;

  import javax.websocket.server.ServerEndpoint;

  /**

  * 功能說明:websocket處理類, 使用J2EE7的標準

  * 切忌直接在該連接處理類中加入業務處理代碼

  */

  //relationId和userCode是我的業務標識參數,websocket.ws是連接的路徑,可以自行定義

  @ServerEndpoint("/websocket.ws/{relationId}/{userCode}")

  public class WebsocketEndPoint {

  private static Log log = LogFactory.getLog(WebsocketEndPoint.class);

  /**

  * 打開連接時觸發

  * @param relationId

  * @param userCode

  * @param session

  */

  @OnOpen

  public void onOpen(@PathParam("relationId") String relationId,

  @PathParam("userCode") int userCode,

  Session session){

  log.info("Websocket Start Connecting: " + SessionUtils.getKey(relationId, userCode));

  SessionUtils.put(relationId, userCode, session);

  }

  /**

  * 收到客戶端消息時觸發

  * @param relationId

  * @param userCode

  * @param message

  * @return

  */

  @OnMessage

  public String onMessage(@PathParam("relationId") String relationId,

  @PathParam("userCode") int userCode,

  String message) {

  return "Got your message (" + message + ").Thanks !";

  }

  /**

  * 異常時觸發

  * @param relationId

  * @param userCode

  * @param session

  */

  @OnError

  public void onError(@PathParam("relationId") String relationId,

  @PathParam("userCode") int userCode,

  Throwable throwable,

  Session session) {

  log.info("Websocket Connection Exception: " + SessionUtils.getKey(relationId, userCode));

  log.info(throwable.getMessage(), throwable);

  SessionUtils.remove(relationId, userCode);

  }

  /**

  * 關閉連接時觸發

  * @param relationId

  * @param userCode

  * @param session

  */

  @OnClose

  public void onClose(@PathParam("relationId") String relationId,

  @PathParam("userCode") int userCode,

  Session session) {

  log.info("Websocket Close Connection: " + SessionUtils.getKey(relationId, userCode));

  SessionUtils.remove(relationId, userCode);

  }

  }

  工具類用來存儲唯一key和連接

  這個是我業務的`需要,我的業務是服務器有對應動作觸發時,推送數據到客戶端,沒有接收客戶端數據的操作。

  import javax.websocket.Session;

  import java.util.Map;

  import java.util.concurrent.ConcurrentHashMap;

  /**

  * 功能說明:用來存儲業務定義的sessionId和連接的對應關系

  * 利用業務邏輯中組裝的sessionId獲取有效連接后進行后續操作

  */

  public class SessionUtils {

  public static Map clients = new ConcurrentHashMap<>();

  public static void put(String relationId, int userCode, Session session){

  clients.put(getKey(relationId, userCode), session);

  }

  public static Session get(String relationId, int userCode){

  return clients.get(getKey(relationId, userCode));

  }

  public static void remove(String relationId, int userCode){

  clients.remove(getKey(relationId, userCode));

  }

  /**

  * 判斷是否有連接

  * @param relationId

  * @param userCode

  * @return

  */

  public static boolean hasConnection(String relationId, int userCode) {

  return clients.containsKey(getKey(relationId, userCode));

  }

  /**

  * 組裝唯一識別的key

  * @param relationId

  * @param userCode

  * @return

  */

  public static String getKey(String relationId, int userCode) {

  return relationId + "_" + userCode;

  }

  }

  推送數據到客戶端

  在其他業務方法中調用

  /**

  * 將數據傳回客戶端

  * 異步的方式

  * @param relationId

  * @param userCode

  * @param message

  */

  public void broadcast(String relationId, int userCode, String message) {

  if (TelSocketSessionUtils.hasConnection(relationId, userCode)) {

  TelSocketSessionUtils.get(relationId, userCode).getAsyncRemote().sendText(message);

  } else {

  throw new NullPointerException(TelSocketSessionUtils.getKey(relationId, userCode) + " Connection does not exist");

  }

  }

  我是使用異步的方法推送數據,還有同步的方法

  客戶端代碼

  var webSocket = null;

  var tryTime = 0;

  $(function () {

  initSocket();

  window.onbeforeunload = function () {

  //離開頁面時的其他操作

  };

  });

  /**

  * 初始化websocket,建立連接

  */

  function initSocket() {

  if (!window.WebSocket) {

  alert("您的瀏覽器不支持websocket!");

  return false;

  }

  webSocket = new WebSocket("ws://127.0.0.1:8080/websocket.ws/" + relationId + "/" + userCode);

  // 收到服務端消息

  webSocket.onmessage = function (msg) {

  console.log(msg);

  };

  // 異常

  webSocket.onerror = function (event) {

  console.log(event);

  };

  // 建立連接

  webSocket.onopen = function (event) {

  console.log(event);

  };

  // 斷線重連

  webSocket.onclose = function () {

  // 重試10次,每次之間間隔10秒

  if (tryTime < 10) {

  setTimeout(function () {

  webSocket = null;

  tryTime++;

  initSocket();

  }, 500);

  } else {

  tryTime = 0;

  }

  };

  }

  其他調試工具

  Java實現一個websocket的客戶端

  依賴:

  <dependency>

  <groupId>org.java-websocket</groupId>

  <artifactId>Java-WebSocket</artifactId>

  <version>1.3.0</version>

  </dependency>

  代碼:

  import java.io.IOException;

  import javax.websocket.ClientEndpoint;

  import javax.websocket.OnError;

  import javax.websocket.OnMessage;

  import javax.websocket.OnOpen;

  import javax.websocket.Session;

  @ClientEndpoint

  public class MyClient {

  @OnOpen

  public void onOpen(Session session) {

  System.out.println("Connected to endpoint: " + session.getBasicRemote());

  try {

  session.getBasicRemote().sendText("Hello");

  } catch (IOException ex) {

  }

  }

  @OnMessage

  public void onMessage(String message) {

  System.out.println(message);

  }

  @OnError

  public void onError(Throwable t) {

  t.printStackTrace();

  }

  }

  import java.io.BufferedReader;

  import java.io.IOException;

  import java.io.InputStreamReader;

  import java.net.URI;

  import javax.websocket.ContainerProvider;

  import javax.websocket.DeploymentException;

  import javax.websocket.Session;

  import javax.websocket.WebSocketContainer;

  public class MyClientApp {

  public Session session;

  protected void start()

  {

  WebSocketContainer container = ContainerProvider.getWebSocketContainer();

  String uri = "ws://127.0.0.1:8080/websocket.ws/relationId/12345";

  System.out.println("Connecting to " + uri);

  try {

  session = container.connectToServer(MyClient.class, URI.create(uri));

  } catch (DeploymentException e) {

  e.printStackTrace();

  } catch (IOException e) {

  e.printStackTrace();

  }

  }

  public static void main(String args[]){

  MyClientApp client = new MyClientApp();

  client.start();

  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

  String input = "";

  try {

  do{

  input = br.readLine();

  if(!input.equals("exit"))

  client.session.getBasicRemote().sendText(input);

  }while(!input.equals("exit"));

  } catch (IOException e) {

  // TODO Auto-generated catch block

  e.printStackTrace();

  }

  }

  }

  chrome安裝一個websocket客戶端調試

  最后

  為了統一的操作體驗,對于一些不支持websocket的瀏覽器,請使用socketjs技術做客戶端開發。

【Java中Websocket使用實例解析】相關文章:

Java中synchronized的使用實例12-03

java讀取解析xml文件實例11-05

Java 異步回調機制實例解析11-30

JAVA中If語句的使用10-03

Java中的多態用法實例分析11-29

Java中shuffle算法的使用12-03

java中通用的線程池實例代碼11-29

Java中的JDBC事務解析11-29

Java中運算符的使用11-18