Spring实战之使用WebSocket和STOMP实现消息功能

本章参考内容《spring实战》集成篇之使用WebSocket和STOMP实现消息功能

使用WebSocket和STOMP实现消息功能

spring为WebSocket通信提供了支持,包括:

  • 发送和接收消息的低层级API;
  • 发送和接收消息的高级API;
  • 用来发送消息的模板;
  • 支持SockJS,用来解决浏览器端、服务器以及代理不支持WebSocket的问题。

我们来一一介绍其中的内容板块,当然,如果你对原生socket编程感兴趣也可以去了解一下,再次强调一下,本文是spirng的WebSocket编程模块。

1 使用Spring的底层级WebSocket API

在介绍WebSocket 之前,有必要了解一下WebSocket到底是什么玩意,。
按照其最简单的形式,WebSocket只是两个应用之间通信的通道。位于WebSocket一端的应用发送消息,另外一端处理消息。因为它是全都可以发送和处理消息。如图所示。
Spring实战之使用WebSocket和STOMP实现消息功能_第1张图片
你需要知道WebSocket 和 Http协议的区别:
由于本模块主讲WebSocket,如果你对WebSocket还没有比较清晰的了解,
去了解下:
关键词----理解WebSocket与轮询、质询(很多其他站的dl有详细的解析,多看几篇,也有利于理解)

好了回到正题

WebSocket通信可以应用于任何类型的应用中,但是WebSocket最常见的应用场景是实现服务器和基于浏览器的应用之间的通信。

为了在Spring使用较低层级的API来处理消息,我们必须编写一个实现WebSocketHandler的类. **WebSocketHandler需要我们实现五个方法。

public interface WebSocketHandler {
    void afterConnectionEstablished(WebSocketSession session) throw Exception;
    void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception;
    void handleTransportError(WebSocketSession session, Throwable exception) throws Exception;
    void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception;
    boolean supportsPartialMessages();
}

字面意思看方法名,定义了涉及到WebSocket通信过程会使用到的内容。
包括消息处理,异常处理,连接断开处理,连接建立处理。

相比直接实现WebSocketHandler,更为简单的方法是扩展AbstractWebSocketHandler,这是WebSocketHandler的一个抽象实现。
注意在springboot2.x很多对抽象实现,都通过default关键字,改成了接口的空实现,
有效规范了编程思想。但是这里并没有使用空实现,
应该抽象类扩张了handleMessage(其实现调用了其他三个消息处理类型,原理很简单,就是if 使用instanceof 判断是否可以强转),如下是扩展的三个抽象方法
这三个方法只是handleMessage()方法的具体化,每个方法对应于某一种特定类型的消息。

  • handleBinaryMessage() //字节数据
  • handlePongMessage() //ping-pong连接–用于确定是否可以连接上
  • handleTextMessage() //文本数据

下面是实现的一个案列

public class MarcoHandler extends AbstractWebSocketHandler {

    private static final Logger logger = LoggerFactory.getLogger(MarcoHandler.class);

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { //处理文本信息
        logger.info("Received message: " + message.getPayload());
        Thread.sleep(2000);//模拟延时
        session.sendMessage(new TextMessage("Polo!")); //发送文本消息
    }

}

当然你觉得想处理特定文本类型的数据单独分离开的话,
spring还提供了扩展TextWebSocketHandlerBinaryWebSocketHandle的方法

  • TextWebSocketHandlerAbstractWebSocketHandler的子类,它会拒绝处理二进制消息。它重载了handleBinaryMessage()方法,如果收到二进制消息的时候,将会关闭WebSocket连接。
  • 与之类似,BinaryWebSocketHandler也是AbstractWeb-SocketHandler的子类,它重载了handleTextMessage()方法,如果接收到文本消息的话,将会关闭连接

小结:

  • WebSocketHandler接口规范了处理WebSocket的不同状态
  • 可以通过重载5个方法实现扩展功能
    • 消息加工
    • 监控连接状态
    • 设置限制条件等
  • 同时还可以通过继承AbstractWebSocketHandler,WebSocketHandler接口的抽象实现
    • 扩展了消息接口(原有的消息接口,转型调用其他三个接口)
    • Text、Binary、Pong(自动回复(ping-pong),案例:和linux或windows,ping连接

2 应对不支持WebSocket的场景

幸好,提到WebSocket的备用方案,这恰是SockJS所擅长的。SockJS让我们能够使用统一的编程模型,就好像在各个层面都完整支持WebSocket一样,SockJS在底层会提供备用方案。
例如,为了在服务端启用SockJS通信,我们在Spring配置中可以很简单地要求添加该功能。重新回顾一下程序清单18.2中的registerWebSocketHandlers()方法,稍微加一点内容就能启用SockJS:

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(marcoHandler(), "/marco").withSockJS();
    }

Xml方式:

img

要在客户端使用SockJS,需要确保加载了SockJS客户端库。具体的做法在很大程度上依赖于使用JavaScript模块加载器(如require.js或curl.js)还是简单地使用

你可能感兴趣的:(spring实战)