第 14 章 创建 Jakarta WebSocket 应用程序

Jakarta WebSocket 协议提供 Web 客户端和服务器之间的双向通信。客户端和服务器之间的通信基于事件,与基于轮询的方法相比,可以更快地处理和缩小带宽。Jakarta WebSocket 使用 JavaScript API 以及使用 Jakarta WebSocket 规格的客户端 Jakarta WebSocket 端点,可用于 Web 应用。

首先作为 HTTP 连接在客户端和服务器之间建立连接。然后,客户端使用 Upgrade 标头请求 Jakarta WebSocket 连接。然后,所有通信都是相同的 TCP/IP 连接的全双工,而数据开销最少。由于每条消息都不包含不必要的 HTTP 标头内容,Jakarta WebSocket 通信需要更小的带宽。其结果是适用于应用程序的低延迟通信路径,需要实时响应。

JBoss EAP Jakarta WebSocket 实施为服务器端点提供全面的依赖注入支持,但它不为客户端端点提供上下文和依赖注入服务。

Jakarta WebSocket 应用程序需要以下组件和配置更改:

创建 Jakarta WebSocket 应用程序

以下代码示例取自 JBoss EAP 附带的 websocket-hello 快速入门。它是 Jakarta WebSocket 应用的一个简单示例,它打开连接、发送消息并关闭连接。它不实施任何其他功能或包含任何错误处理,这是真实应用所需要的。

  1. 创建 JavaScript HTML 客户端。

    以下是 Jakarta WebSocket 客户端的示例。它包含这些 JavaScript 功能:

    • connect() :此功能创建通过 Jakarta WebSocket URI 的 Jakarta WebSocket 连接。资源位置与服务器端点类中定义的资源匹配。此功能还会截获和处理 Jakarta WebSocket onopen、onmessage、onerroronclose
    • sendMessage() :此功能获取表单中输入的名称,创建消息并使用 WebSocket.send()命令发送。
    • disconnect() :此功能会发出 WebSocket.close()命令。
    • displayMessage() :此功能将页面上的显示消息设置为 Jakarta WebSocket endpoint 方法返回的值。
    • DisplayStatus() :此函数显示 Jakarta WebSocket 连接状态。

      示例:应用程序 index.html Code

      <html>
        <head>
          <title>WebSocket: Say Hello</title>
          <link rel="stylesheet" type="text/css" href="resources/css/hello.css" />
          <script type="text/javascript">
            var websocket = null;
            function connect() {
              var wsURI = 'ws://' + window.location.host + '/websocket-hello/websocket/helloName';
              websocket = new WebSocket(wsURI);
              websocket.onopen = function() {
                  displayStatus('Open');
                  document.getElementById('sayHello').disabled = false;
                  displayMessage('Connection is now open. Type a name and click Say Hello to send a message.');
              };
              websocket.onmessage = function(event) {
                  // log the event
                  displayMessage('The response was received! ' + event.data, 'success');
              };
              websocket.onerror = function(event) {
                  // log the event
                  displayMessage('Error! ' + event.data, 'error');
              };
              websocket.onclose = function() {
                  displayStatus('Closed');
                  displayMessage('The connection was closed or timed out. Please click the Open Connection button to reconnect.');
                  document.getElementById('sayHello').disabled = true;
              };
            }
            function disconnect() {
              if (websocket !== null) {
                  websocket.close();
                  websocket = null;
              }
              message.setAttribute("class", "message");
              message.value = 'WebSocket closed.';
              // log the event
            }
            function sendMessage() {
              if (websocket !== null) {
                  var content = document.getElementById('name').value;
                  websocket.send(content);
              } else {
                  displayMessage('WebSocket connection is not established. Please click the Open Connection button.', 'error');
              }
            }
            function displayMessage(data, style) {
              var message = document.getElementById('hellomessage');
              message.setAttribute("class", style);
              message.value = data;
            }
            function displayStatus(status) {
              var currentStatus = document.getElementById('currentstatus');
              currentStatus.value = status;
            }
          </script>
        </head>
        <body>
          <div>
            <h1>Welcome to Red Hat JBoss Enterprise Application Platform!</h1>
            <div>This is a simple example of a Jakarta WebSocket implementation.</div>
            <div id="connect-container">
              <div>
                <fieldset>
                  <legend>Connect or disconnect using websocket :</legend>
                  <input type="button" id="connect" onclick="connect();" value="Open Connection" />
                  <input type="button" id="disconnect" onclick="disconnect();" value="Close Connection" />
                </fieldset>
              </div>
              <div>
                  <fieldset>
                    <legend>Type your name below, then click the `Say Hello` button :</legend>
                    <input id="name" type="text" size="40" style="width: 40%"/>
                    <input type="button" id="sayHello" onclick="sendMessage();" value="Say Hello" disabled="disabled"/>
                  </fieldset>
              </div>
              <div>Current WebSocket Connection Status: <output id="currentstatus" class="message">Closed</output></div>
              <div>
                <output id="hellomessage" />
              </div>
            </div>
          </div>
        </body>
      </html>

  2. 创建 Jakarta WebSocket 服务器端点。

    您可以使用以下任一方法之一创建 Jakarta WebSocket 服务器端点:

    • 编程端点 :端点扩展端点类。
    • 标注 的端点 :端点类使用注释来与 Jakarta WebSocket 事件交互。代码比编程端点更容易。

    以下代码示例使用注解的端点方法并处理以下事件:

    • @ServerEndpoint 注释将此类识别为 Jakarta WebSocket 服务器端点,并指定路径。
    • 打开 Jakarta WebSocket 连接时会触发 @OnOpen 注释。
    • 收到消息时会触发 @OnMessage 注释。
    • 当 Jakarta WebSocket 连接关闭时,会触发 @OnClose 注释。

      示例:Jkarta WebSocket Endpoint Code

      package org.jboss.as.quickstarts.websocket_hello;
      
      import javax.websocket.CloseReason;
      import javax.websocket.OnClose;
      import javax.websocket.OnMessage;
      import javax.websocket.OnOpen;
      import javax.websocket.Session;
      import javax.websocket.server.ServerEndpoint;
      
      @ServerEndpoint("/websocket/helloName")
      public class HelloName {
      
          @OnMessage
          public String sayHello(String name) {
              System.out.println("Say hello to '" + name + "'");
              return ("Hello" + name);
          }
      
          @OnOpen
          public void helloOnOpen(Session session) {
              System.out.println("WebSocket opened: " + session.getId());
          }
      
          @OnClose
          public void helloOnClose(CloseReason reason) {
              System.out.println("WebSocket connection closed with CloseCode: " + reason.getCloseCode());
          }
      }

  3. 在项目 POM 文件中声明 Jakarta WebSocket API 依赖项。

    如果使用 Maven,请将以下依赖项添加到 pom.xml 项目:

    示例:Maven 依赖性

    <dependency>
      <groupId>org.jboss.spec.javax.websocket</groupId>
      <artifactId>jboss-websocket-api_1.1_spec</artifactId>
      <scope>provided</scope>
    </dependency>

JBoss EAP 随附的快速入门包括额外的 Jakarta WebSocket 客户端和端点代码示例。