第二章、WebSocket的应用

本文介绍了Java WebSocket API的基础知识,涵盖了端点创建、消息收发、连接管理等内容,并对比了程序化端点与注解端点的不同实现方式。

Java WebSocket应用程序由websocket端点组成. Websocket端点是一个java对象,代表两个对等方之间Websocket连接的一端

可以通过两种主要方法创建端点,第一种方法是使用所需的行为来实现Java WebSocket API中的某些API类,以及处理端点的生命周期,消费和发送消息,发布自身或连接到对等方。通常,本规范会将此类端点称为程序化端点。第二种方法是用Java WebSocket API 中的某些注解来装饰Plain Old Java Object (POJO). 然后,实现将采用这些带注解的类,并在运行时创建适当的对象,以将POJO部署为websocket端点。通常,本规范将这种端点称为带注解的端点。规范在谈论任何一种端点(编程的或带注解的)时都将引用该端点。

端点参与建立websocket连接的开发握手,端点通常将发送和接收各种websocket消息,当websocket连接关闭时,端点生命周期即将结束。

2.1 API 预览

  • 本节简要概述了java websocket API,以便为随后的详细介绍奠定基础。

2.1.1、端点生命周期

  • 在Java WebSocket API 中一个逻辑websocket端点代表实例化一个Endpoint的类。开发人员可以使用公共的具体的Endpoint子类以拦截端点的生命周期事件:对等连接的事件,打开连接结束,以及在端点的生存期内出现错误。
  • 除非由开发人员提供的配置程序进行了其他替代(请参见3.1.7),否则websocket实现必须为Endpoint 类的每个VM每个应用程序使用一个实例来表示每个已连接对等方的逻辑端点,[WSC 2.1.1-1]在这种典型情况下,Endpoint类的每个实例仅处理从一个并且只有一个对等点端点的连接。

2.1.2、会话

  • Java WebSocket API使用Session类的实例对端点及其每个对等节点之间的交互序列进行建模。对等点与端点之间的交互以打开通知开始,然后是端点与对等点之间的一定数量的websocket消息(可能为零),然后是关闭通过或可能是致命错误(终止连接)。对于与端点交互的每个对等方,都有一个唯一的Session实例表示该交互。[WSC2.1.2-1]将该与该对等方的连接相对应的session实例传递到代表其生命周期中关键事件上的逻辑端点的端点实例。
  • 开发人员可以使用可通过Session对象上的getUserProperties() 调用访问的用户属性映射,以将应用程序特定信息与特定会话相关联。websocket实现必须保留此会话数据以供以后访问,直到实例调用onClose()方法完成为止,[WSC2.1.2-2]. 在那之后,允许websocket实现丢弃开发人员数据。如果选择发布实例的websocket实现可以发布新的唯一会话ID,则此时可以重用同一会话实例来表示新连接[WSC 2.1.2-3]
  • 在故障转移的情况下,作为分布式容器一部分的websocket实现可能需要将websocket会话从一个节点迁移到另一个节点,如果数据标记为java.io.Serializable, 则需要实现以保留插入到Websocket会话中的开发人员数据对象。[WSC 2.1.2-4]

2.1.3、接收消息

  • Java WebSocket API 为端点提供了多种从端点接收消息的方法,开发人员实现了最适合其需求的适合消息传递的样式的MessageHandler接口的子类型。并通过在对应于对等方的Session实例上注册处理程序来对来自特定对等方的消息进行处理。
  • WebSocket API将每个会话的MessageHandler注册限制为每个本机Websocket消息类型一个MessageHandler,[WSC-2.1.3-1]换句话说,开发人员最多只能注册一个MessageHandler用于传输文本消息,一个MassageHandler用于传入的二进制消息,以及一个MessageHandler用于传入的Pong消息,如果违反此限制,则WebSocket实现必须生成一个错误(WSC-2.1.3.2]
  • 未来版本的规范可能会解除此限制。
  • Session.addMessageHandler(MessageHandler) 方法并非在所有情况下都安全使用,尤其在使用Lambda表达式时,API强制实现在运行时获取MessageHandler的类型参数,但是这并非总是可能的。可以安全使用此方法的唯一情况是,直接将MessageHandler.Whole或MessageHandler.Partial实现为匿名类。这种方法保证了通用类型信息将出现在生成的类文件中,并且运行时将能够获取它,对于任何其他情况(包括Lambda表达式),必须使用以下方法之一:Session.addMessageHandler(Class, MessageHandler.Partial) 或 Session.addMessageHandler(Class, MessageHandler.Whole)

2.1.4、发送消息

  • Java WebSocket API 使用端点作为RemoteEndpoint接口的实例来模拟会话的每个对等方。此接口及其两个子类型(RemoteEndpoint.Whole和RemoteEndpoint.Partial)包含用于从端点向其对等方发送Websocket消息的多种方法。

  • 例子

  • 这是一个服务器端点的示例,该端点等待传入的文本消息,并在收到发送给它的客户端的消息时立即响应,显示了示例的端点,首先仅使用API类

    • public class HelloServer extends Endpoint{
        @Override
        public void onOpen(Session session, EndPointConfig ec){
          final RemoteEndpoint.Basic remote = session.getBasicRemote();
          session.addMessageHandler(String.class, new 			MessageHandler.Whole<String>(){
            public void onMessage(String text){
              try{
                remote.sendText("获取到你消息("+text+"). Thank!");
              }catch(IOException ioe){
                ioe.printStackTrace();
              }
            }
          });
        }
      
      }
      
  • 第二例子使用注册方式

    • @ServerEndpoint("/hello")
      public class MyHelloServer{
        @OnMessage
        public String handleMessage(String message){
          return "获取到你消息("+text+"). Thank!";
        }
      }
      
  • 注意: 这两个示例几乎是等效的,但是带有注解的端点配置了自己的路径映射。

2.1.5、关闭连接

  • 如果出于某种原因要关闭到websocket端点的打开连接,无论是由于从对等方接收到websocket关闭事件,还是由合理原因关闭连接,则websocket实际必须调用websocket端点的onClose()方法。[WSC 2.1.5-1]
  • 如果关闭是由远程对等方发起的,则实现必须使用在websocket协议关闭帧中发送关闭代码和原因,如果关闭是由本地容器发起的,例如,如果本地容器确实会话已超时,则本地实现必须使用websocket协议关闭代码1006(该代码特别禁止在网络上的关闭帧中使用)并且有合适利用,这样端点可以确定关闭是远程启动还是本地启动。如果会话在本地关闭,则实现必须在调用websocket端点的onClose() 方法之间尝试发送websocket关闭帧。

2.1.6、客户端和服务器

  • websocket协议是一种双向协议,一旦建立,websocket协议在对话中的双方之间是对等的。webSocket客户端和websocket服务器之间的区别仅在于双方之间的连接方式。在本规范中,我们将说一个websocket客户端是一个websocket端点。它发起与对等方的连接,我们将说一个websocket服务器是一个已发布的websocket端点。正在等待来自对等方的连接。在大多数部署中,一个websocket客户端将仅连接到一个websocket服务器,并且一个websocket服务器将接受来自多个客户端的连接。
  • 因此,WebSocket API 对应WebSocket客户端端点与Websocket服务器的端点的区别仅仅在于服务器端需要启动时候需要进行配置。

2.1.7、WebSocketContainers(weksocket容器)

  • webSocket实现代表的应用是实例化WebSocketContainer类。每个WebSocketContainer实例都有许多配置属性,这些属性适用于部署在其中的端点。在WebSocket实现的服务器部署中,每个Java JM每个应用程序都有一个唯一的WebSocketContainer实例。[WSC2.1.7-1]在websocket实现的客户端部署中,应用程序从ContainerProvider类获取WebSocketContainer的实例。

2.2、WebSocket端点的注解

  • java注解已被广泛用作向Java对象添加部署特征的一种方法,尤其是在Java EE平台中。Java WebSocket规范定义了少量的websocket注解,这些 注解允许开发人员采用Java类并将其转换为websocket端点。本节提供了简短的概述,为在本规范后面部分详细介绍奠定了基础。

2.2.1、端点相关注解

  • 类级别的@ServletEndpoint注解指示Java类将在运行时成为websocket端点。开发人员可以使用value属性为端点指定URI映射,编码器和解码器属性运行开发人员指定类,这些类将应用程序对象编码为websocket消息和解码器将websocket消息解码为应用程序对象。

2.2.2、Websocket 生命周期

  • 在使用@ServerEndpoint注解的Java类中可以使用@OnOpen和@OnClose方法级别的注解进行进一步装饰,以指定当结果端点接收到来自对等方的新连接或来自对等方的连接或关闭,实现必须调用这些方法。[WSC 2.2.2-1]

2.2.3、处理消息

  • 为了使得带注解的端点可以处理传入消息,方法级别@OnMessage注解允许开放人员指示在接收到消息时,这些实现必须调用的方法。

2.2.4、处理异常

  • 为了使得带注解的端点可以处理由外部事件引起的错误,例如正在解码传入的消息时,带注解的端点可以使用@OnError注解来标记其方法之一,该实现必须由有关实现的信息调用,每当发生此类错误时,都会显示该错误 [WSC 2.2.4-1]

2.2.5、Ping/Pong机制

  • websocket协议中的ping/pong机制用于检查连接是否仍处于活动状态。遵循协议的要求,如果websocket实现从对等方收到ping消息,则它必须尽快用包含相同应用程序数据的pong消息对该对等方进行响应。[WSC 2.2.5-1]希望发送单向pong消息的开发人员可以使用RemoteEndpoint API进行发送,希望监听器返回的pong消息的开发人员可以为它们定义MessageHandler, 也可以使用@OnMessage注解对方法进行注解,期权该方法将PongMessage规定为其消息实体参数,在任何一种情况下,如果实现收到发往此端点的pong消息,则它必须调用改MessageHandler或带注解的消息

2.3、Java WebSocket 客户端API

  • 该规范定义了Java WebSocket API的两个配置,Java WebSocketAPI 用于表示本规范中定义的全部功能。该API既可以作为独立的WebSocket实现,作为Java Servlet容器的一部分,也可以作为完整Java EE平台的一部分实现,必须实现以符合Java WebSocket API 的API是包javax.websocket.* 和javax.websocket.server.* 中所有java API。如果将API作为完整Java EE 平台的一部分实现,则Java WebSocket API的某些非API功能是可选的,例如,要求websocket端点必须是非上下文托管的bean(请参见第7章),此类仅Java EE的功能在描述它们的位置明确标记
  • Java WebSocket API 还包含其功能的子集,旨在用于台式机,平板电脑或智能手机设备。此子集不包含部署服务端点的功能。此子集称为Java WebSocket客户端API,必须实现以符合Java WebSocket Client API的API包 javax.websocket.*中的所有Java API。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值