Spring WebSocket详解
作者:chszs,转载需注明。博客主页:http://blog.csdn.net/chszs
Spring框架从4.0版开始支持WebSocket,下面我将详述Spring WebSocket库的相关内容。内容包括Spring框架是如何在Web应用中支持WebSocket方式的消息通信,以及如何利用STOMP协议作为应用层的协议——WebSocket的子协议。
1、WebSocket协议介绍
WebSocket协议是RFC-6455规范定义的一个Web领域的重要的功能:全双工,即客户端和服务器之间的双向通信。它是一个令人兴奋的功能,业界在此领域上已经探索很久,使用的技术包括Java Applet、XMLHttpRequest、Adobe Flash、ActiveXObject、各种Comet技术、服务器端的发送事件等。
需要理解一点,在使用WebSocket协议前,需要先使用HTTP协议用于构建最初的握手。这依赖于一个机制——建立HTTP,请求协议升级(或叫协议转换)。当服务器同意后,它会响应HTTP状态码101,表示同意切换协议。假设通过TCP套接字成功握手,HTTP协议升级请求通过,那么客户端和服务器端都可以彼此互发消息。
Spring框架4.0以上版本引入了一个新模块,即spring-websocket模块。它对WebSocket通信提供了支持。它兼容Java WebSocket API规范JSR-356,同时提供了额外的功能
2、WebSocket的降级选项
浏览器对WebSocket的支持并不快,IE浏览器是第10版才开始支持的。此外,一些代理工具也会限制WebSocket通信。因此,即使是现在要开发WebSocket应用,降级选项是必不可少的,以便在不支持的场景使用模拟WebSocket API的工作方式。Spring框架提供了这种透明的降级方案——使用SockJS协议。此方案可以通过配置来自动切换,无需修改应用程序的代码。
3、消息通信架构
使用WebSocket除了开发方面的挑战外,还有一个难点在于设计上的考虑。
目前REST架构是一个广泛接受、易于理解、适合构建现代Web应用的架构。REST架构依赖于很多URL、和几个HTTP方法,使用了链接、保持无状态等原则。
相比之下WebSocket应用可能只使用一个URL用于最初的HTTP握手。随后所有的消息都共享此TCP连接,消息在此连接上双向流动。这一点可见,它与REST架构是完全不同的,是异步的、事件驱动的、消息传递的架构。WebSocket架构与传统的消息传输方案(如JMS、AMQP)比较相似。
Spring框架4.0引入了一个新模块——spring-messaging模块,它包含了很多来自于Spring Integration项目中的概念抽象,比如:Message消息、消息频道MessageChannel、消息句柄MessageHandler等。此模块还包括了一套注释,可以把消息映射到方法上,与Spring MVC基于注释的编程模型相似。
4、WebSocket支持子协议
WebSocket只是一个消息传递的体系结构,它没有指定任何特定的消息传递协议。它是一个TCP协议之上的超薄层,可以把字节流转换成消息流(文本货二进制)。随后由应用程序来解释消息。
与HTTP协议不同,WebSocket协议只是一个应用级的协议,它非常简单,并不能理解传入的消息,也不能对消息进行路由或处理。因此WebSocket协议是应用级协议的底层,其上需要一个框架来理解和处理消息。
出于这个原因,WebSocket RFC定义了子协议的使用。在握手过程中,客户端和服务器端可以使用Header部分的Sec-WebSocket-Protocol来协商使用的子协议——也即使用更高级的应用级协议。子协议的使用不是必须的,但即使不使用子协议,应用程序仍然需要选择一个消息格式——让客户端和服务器相互可以理解的格式。这种格式可以自定义,或特定于框架,或使用标准的消息传递协议。
Spring框架提供了对使用STOMP子协议的支持。
STOMP,Streaming Text Orientated Message Protocol,流文本定向消息协议。STOMP是一个简单的消息传递协议, 是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。
STOMP提供了一个可互操作的连接格式,允许STOMP客户端与任意STOMP消息代理(Broker)进行交互,类似于OpenWire协议(一种二进制协议)。
5、什么场景下该使用WebSocket
在Web应用中,客户端和服务器端需要以较高频率和较低延迟来交换事件时,适合用WebSocket。因此WebSocket适合财经、游戏、协作等应用场景。
对于其他应用场景则未必适合。例如,某个新闻订阅需要显示突发新闻,使用间隔几分钟的长轮询也是可以的,这里的延迟可以接受。
即使在要求低延迟的应用场景,如果传输的消息数很低(比如监测网络故障的场景),那么应该考虑使用长轮询技术。
而只有在低延迟和高频消息通信的场景下,选用WebSocket协议才是非常适合的。即使是这样的应用场景,仍然存在是选择WebSocket通信呢?又或者是选择REST HTTP通信呢?
答案是会根据应用程序的需求而定。但是,也可能同时使用这两种技术,把需要频繁交换的数据放到WebSocket中实现,而把REST API作为过程性的业务的实现技术。另外,当REST API的调用中需要把某个信息广播给多个客户端是,也可以通过WebSocket连接来实现。
Spring框架提供了@Controller注释和@RestController注释,两者都可以用于HTTP请求的处理以及WebSocket消息的处理。另外,Spring MVC的请求处理方法,或其它应用程序的请求处理方法,都可以很容易地使用WebSocket协议来广播消息到所有感兴趣的客户端或指定用户。