是否可以使用Spring-WebSockets通过WebSockets通过STOMP发送二进制数据?

时间:2014-10-06 09:55:19

标签: javascript spring websocket stomp spring-websocket

我可以在spring documentation之后通过WebSockets发送和接收带有STOMP的JSON。但是,在高速率的情况下性能很差,所以我希望描述二进制消息的使用。

  • Spring-WebSockets 4.0
  • 在Chrome 35中运行的JavaScript客户端
  • stomp.js 1.7.1

发送

我使用SimpMessageTemplate发送消息和必要的代理中继 - 请参阅spring documentation

@Controller
public class DemoBinaryController {
   @Autowired
   private SimpMessagingtemplate template

   @Scheduled(fixedDelay = 5000)
   public void demo() throws Exception {
      GenericMessage<byte[]> message = new GenericMessage<byte[]>(new byte[]{65,66,67});
      template.send("/app/binarydemo", message);
   }
}

接收

JavaScript客户端使用标准机制使用stomp.js接收数据。

var subscription = client.subscribe("/app/binarydemo", new function(message) {
   console.log("RX message", typeof message.body, message.body.length);
});

收到消息,但是作为字符串,控制台输出如下。我期待一些原始类型,比如ArrayBuffer

RX message string  3
RX message string  3

我尝试过的事情

我意识到STOMP中的T代表Text,但是Spring文档意味着二进制消息至少可以使用普通WebSockets,stomp specification状态

  

STOMP是基于文本的,但也允许传输二进制文件   消息。

  • 调试发送代码,就我所见,它似乎仍然是byte []
  • 接收时调试stomp.js库。在底层ws.onmessage回调中收到该消息似乎是一个字符串(stomp-1.7.1.js中的第243行)
  • 很多搜索 - 这似乎是一个罕见的主题,信息很少
  • 查看stomp.js源代码。对二进制的唯一引用是ws.binaryType =“arraybuffer”。

更新:我在服务器端做了更多的调试。似乎org.springframework.web.socket.TextMessage总是在org.springframework.web.socket.messaging.StompSubProtocolHandler内而不是org.springframework.web.socket.BinaryMessage中使用。我已经针对此SPR-12301

提出了功能请求
message = MessageBuilder.withPayload(message.getPayload()).setHeaders(headers).build();
byte[] bytes = this.stompEncoder.encode((Message<byte[]>) message);

synchronized(session) {
    session.sendMessage(new TextMessage(new String(bytes, UTF8_CHARSET)));
}

我的问题

  • 这种方法可以采用这种方法吗?
  • 我错过了一些关键步骤吗?
  • 任何人都可以指出我的工作实例

2 个答案:

答案 0 :(得分:9)

org.springframework.web.socket.TextMessage似乎总是在org.springframework.web.socket.messaging.StompSubProtocolHandler而不是org.springframework.web.socket.BinaryMessage中使用。我已经为此SPR-12301提出了一项已被接受的功能请求。

message = MessageBuilder.withPayload(message.getPayload()).setHeaders(headers).build();
byte[] bytes = this.stompEncoder.encode((Message<byte[]>) message);

synchronized(session) {
    session.sendMessage(new TextMessage(new String(bytes, UTF8_CHARSET)));
}

更新

  • SPR-12301已在4.1.2中提供,但仅添加了对接收二进制消息的支持
  • 提升SPR-12475发送二进制邮件

答案 1 :(得分:1)

尝试使用ByteArrayMessageConverter

配置服务器
@Configuration
@EnableWebSocketMessageBroker
public class MyWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

   @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
        messageConverters.add(new ByteArrayMessageConverter());
        return false;
    }

}

<强>更新

啊!我看到。感谢:

public TextMessage(byte[] payload) {
    super(new String(payload, UTF_8));
    this.bytes = payload;
}

来自STOMP规范的另一面:

  

STOMP消息的主体必须是String。如果要发送和接收JSON对象,...

根据ArrayBuffer

  

从现有数据中获取数组缓冲区

     
      
  • 来自Base64字符串
  •   
  • 来自本地档案
  •   

所以,我认为你没有chioce而不是提供一些自定义MessageConverter,它会将你的byte[]转换为Base64字符串并发送它。

在JavaScript方面,您应该以某种方式将该字符串解码为ArrayBuffer