Spring 中的WebSocket

一、WebSocket

按照其最简单的形式,WebSocket只是两个应用之间通信的通道。位于WebSocket一端的应用发送消息,另外一端处理消息。因为它是全双工的,所以每一端都可以发送和处理消息。
在这里插入图片描述
WebSocket通信可以应用于任何类型的应用中,但是WebSocket最常见的应用场景是实现服务器和基于浏览器的应用之间的通信。浏览器中的JavaScript客户端开启一个到服务器的连接,服务器通过这个连接发送更新给浏览器。相比历史上轮询服务端以查找更新的方案,这种技术更加高效和自然。

1.1 编写WebSocket

为了在Spring使用较低层级的API来处理消息,我们必须编写一个实现WebSocketHandler的类:

package org.springframework.web.socket;

public interface WebSocketHandler {
    void afterConnectionEstablished(WebSocketSession var1) throws Exception;

    void handleMessage(WebSocketSession var1, WebSocketMessage<?> var2) throws Exception;

    void handleTransportError(WebSocketSession var1, Throwable var2) throws Exception;

    void afterConnectionClosed(WebSocketSession var1, CloseStatus var2) throws Exception;

    boolean supportsPartialMessages();
}

可以看到,WebSocketHandler需要我们实现五个方法。相比直接实现WebSocketHandler,更为简单的方法是扩展AbstractWebSocketHandler,这是WebSocketHandler的一个抽象实现。如下的程序清单展现了MarcoHandler,它是AbstractWebSocketHandler的一个子类,会在服务器端处理消息。

1) 创建WebSocket消息处理类

在这里插入图片描述
尽管AbstractWebSocketHandler是一个抽象类,但是它并不要求我们必须重载任何特定的方法。相反,它让我们来决定该重载哪一个方法。除了重载WebSocketHandler中所定义的五个方法以外,我们还可以重载AbstractWebSocketHandler中所定义的三个方法:

  • handleBinaryMessage()
  • handlePongMessage()
  • handleTextMessage()

这三个方法只是handleMessage()方法的具体化,每个方法对应于某一种特定类型的消息。

MarcoHandler所没有重载的方法都由AbstractWebSocketHandler以空操作的方式(no-op)进行了实现。这意味着MarcoHandler也能处理二进制和pong消息,只是对这些消息不进行任何操作而已。

另外一种方案,我们可以扩展TextWebSocketHandler,不再扩展AbstractWebSocketHandler:
在这里插入图片描述
TextWebSocketHandler是AbstractWebSocketHandler的子类,它会拒绝处理二进制消息。它重载了handleBinaryMessage()方法,如果收到二进制消息的时候,将会关闭WebSocket连接。与之类似,BinaryWebSocketHandler也是AbstractWebSocketHandler的子类,它重载了handleTextMessage()方法,如果接收到文本消息的话,将会关闭连接。

尽管你会关心如何处理文本消息或二进制消息,或者二者兼而有之,但是你可能还会对建立和关闭连接感兴趣。在本例中,我们可以重载afterConnectionEstablished()和afterConnectionClosed():
在这里插入图片描述
我们通过afterConnectionEstablished()和afterConnectionClosed()方法记录了连接信息。当新连接建立的时候,会调用afterConnectionEstablished()方法,类似地,当连接关闭时,会调用afterConnectionClosed()方法。在本例中,连接事件仅仅记录了日志,但是如果我们想在连接的生命周期上建立或销毁资源时,这些方法会很有用。

2)开启Spring的WebSocket功能

在Spring的Java配置中,这需要在一个配置类上使用@EnableWebSocket,并实现WebSocketConfigurer接口,如下面的程序清单所示。
在这里插入图片描述
registerWebSocketHandlers()方法是注册消息处理器的关键。通过重载该方法,我们得到了一个WebSocketHandlerRegistry对象,通过该对象可以调用addHandler()来注册信息处理器。在本例中,我们注册了MarcoHandler(以bean的方式进行声明)并将其与“/marco”路径相关联。

另外,如果你更喜欢使用XML来配置Spring的话,那么可以使用websocket命名空间:
在这里插入图片描述

3)创建webSocket客户端

在这里插入图片描述

1.2 应对不支持WebSocket的场景

WebSocket是一个相对比较新的规范。虽然它早在2011年底就实现了规范化,但即便如此,在Web浏览器和应用服务器上依然没有得到一致的支持。Firefox和Chrome早就已经完整支持WebSocket了,但是其他的一些浏览器刚刚开始支持WebSocket。

幸好,提到WebSocket的备用方案,这恰是SockJS所擅长的。SockJS是WebSocket技术的一种模拟,在表面上,它尽可能对应WebSocketAPI,但是在底层它非常智能,如果WebSocket技术不可用的话,就会选择另外的通信方式。SockJS会优先选用WebSocket,但是如果WebSocket不可用的话,它将会从如下的方案中挑选最优的可行方案:

  • XHR流。
  • XDR流。
  • iFrame事件源。
  • iFrame HTML文件。
  • XHR轮询。
  • XDR轮询。
  • iFrame XHR轮询。
  • JSONP轮询。

好消息是在使用SockJS之前,我们并没有必要全部了解这些方案。SockJS让我们能够使用统一的编程模型,就好像在各个层面都完整支持WebSocket一样,SockJS在底层会提供备用方案。

1)启用SockJS

在这里插入图片描述

如果你使用XML来配置Spring的话,启用SockJS只需在配置中添加<websocket:sockjs>元素即
可:
在这里插入图片描述

2) 在客户端使用SockJS

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

书香水墨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值