官网英文参考:
中文解析:
Websocket的Java API提供提供转码和反转码的功能实现 Websocket Message和 Java类型相互转化。转码是指 利用Java对象转化为一个可以传输的Websocket Message(其格式有json,xml,二进制)。反转码实现相反的功能,即读消息,转化为Java对象。
这个机制使得编写Websocket应用更加容易,因为他将业务逻辑从序列化和反序列化中分离出来。
7.1 Implementing Encoders to Convert Java Objects into WebSocket Messages
endpoint端点实现和使用编码过程如下:
1. 实现下面任意一个接口:
-
Encoder.Text<T>
for text messages -
Encoder.Binary<T>
for binary messages
这些接口指定了转码方法,可以为你想发送的每一个Java类型定义一个转码类。
2. 将你实现的转码类添加到注解的ServerEndpoint 中作为encoders一个可选参数。
3. 用RemoteEndpoint.Basic 或者是RemoteEndpoint.Async接口的sendObject(Object data)方法发送转码的消息。容器将会去寻找你所传Java类型一致的转码类,并将其转码为Websocket Message。
下面是一个例子:假如有MessageA和MessageB两个Java 类,你想将其转化为文本消息,如下所示实现Encoder.Text<MessageA>和Encoder.text<MessageB>两个接口:
public class MessageATextEncoder implements Encoder.Text<MessageA> { @Override public void init(EndpointConfig ec) { } @Override public void destroy() { } @Override public String encode(MessageA msgA) throws EncodeException { // Access msgA's properties and convert to JSON text... return msgAJsonString; } }
实现MessageB同上。
然后就是将其添加到ServerEndPoint 的encoders 参数中:
@ServerEndpoint( value = "/myendpoint", encoders = { MessageATextEncoder.class, MessageBTextEncoder.class } ) public class EncEndpoint { ... }
现在你可以如下图所示,利用sendObject方法发送MessageA和MessageB两个Java对象了。
MessageA msgA = new MessageA(...); MessageB msgB = new MessageB(...); session.getBasicRemote.sendObject(msgA); session.getBasicRemote.sendObject(msgB);
如上面提到的例子,你可以实现多个转码为文本,或者是转码为二进制的类。像endpoint一样,转码对象也只会有且关联一个Websocket连接,任何时刻也只会有一个线程在执行转码代码。
7.2 Implementing Decoders to Convert WebSocket Messages into Java Objects
server端点解码的过程如下:
1.实现下面任意一个接口
-
Decoder.Text<T>
for text messages -
Decoder.Binary<T>
for binary messages
这些接口指定了两个 decode和willDecode方法。
Note: Unlike with encoders, you can specify at most one decoder for binary messages and one decoder for text messages. |
注意不像是编码(转码),你最多实现一个二进制消息解码类和最多一个文本消息解码类
2. 将解码类的名字添加到ServerEndPoint类中作为decoders的一个可选参数。
3. 在endpoint中注解OnMessage方法,从而指定一个方法将Java类型作为一个参数。但server端点收到一个消息,就会利用你指定的其中一个解码类解码,而容器就会调用注解OnMessage 并且有Java类型作为参数的方法 。
下面是一个例子,你有两种Java类(
MessageA
and
MessageB
),你想通过文本消息的格式发送和接收。首先你需要定义个父类Message,让
MessageA
and
MessageB继承
,因为你只能定义一个解码文本消息的解码类。实现如下所示:
public class MessageTextDecoder implements Decoder.Text<Message> { @Override public void init(EndpointConfig ec) { } @Override public void destroy() { } @Override public Message decode(String string) throws DecodeException { // Read message... if ( /* message is an A message */ ) return new MessageA(...); else if ( /* message is a B message */ ) return new MessageB(...); } @Override public boolean willDecode(String string) { // Determine if the message can be converted into either a // MessageA object or a MessageB object... return canDecode; } }
然后就是其添加到ServerEndPoint 对应的decoders 参数中。如下所示:
@ServerEndpoint( value = "/myendpoint", encoders = { MessageATextEncoder.class, MessageBTextEncoder.class }, decoders = { MessageTextDecoder.class } ) public class EncDecEndpoint { ... }
现在去endpoint类中定义一个方法,用来接收
MessageA
and
MessageB
消息
@OnMessage public void message(Session session, Message msg) { if (msg instanceof MessageA) { // We received a MessageA object... } else if (msg instanceof MessageB) { // We received a MessageB object... } }
像endpoint一样,解码对象也有且只会关联一个Websocket 连接,所以任何时候,都已有一个线程在执行解码代码。