WebSocket API
框架提供了一个 WebSocket API,您可以使用它来编写处理 WebSocket 消息的客户端和服务器端应用程序。
WebSocketHandler
创建一个 WebSocket 服务器就像实现 WebSocketHandler
一样简单,或者更可能是扩展 TextWebSocketHandler
或 BinaryWebSocketHandler
中的一个。
以下示例使用了 TextWebSocketHandler
:
public class MyHandler extends TextWebSocketHandler {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
// ...
}
}
有专门的 WebSocket 编程配置支持,用于将前面的 WebSocket 处理程序映射到特定的 URL,如下例所示:
@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler");
}
@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}
前面的示例适用于 Web MVC 应用程序,并应包含在 DispatcherHandler
的配置中。
然而 WebSocket 支持不依赖于 Web MVC。通过
WebSocketHttpRequestHandler
的帮助,将 WebSocketHandler
集成到其他 HTTP 服务环境中相对简单。
WebSocket 握手
通过 HandshakeInterceptor
是定制初始 HTTP WebSocket 握手请求的最简单方法,它公开了 "before"
和 "after"
握手的方法。
您可以使用此类拦截器来阻止握手或使任何属性可用于 WebSocketSession
。
以下示例使用内置拦截器将 HTTP 会话属性传递到 WebSocket 会话:
@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new MyHandler(), "/myHandler");
//.addInterceptors(new WebSessionHandshakeInterceptor());
}
}
更高级的选项是扩展 DefaultHandshakeHandler
,它执行 WebSocket 握手的步骤,
包括验证客户端来源、协商子协议和其他细节。如果应用程序需要配置自定义的 RequestUpgradeStrategy
以适应尚不支持的 WebSocket 服务器引擎和版本(有关此主题的更多信息,
请参见 部署)时,也可能需要使用此选项。
Java 配置和 XML 命名空间都可以配置自定义的 HandshakeHandler
。
Infra 提供了一个 WebSocketHandlerDecorator 基类,您可以使用它来装饰 WebSocketHandler ,以添加额外的行为。
在使用 WebSocket Java 配置或 XML 命名空间时,默认情况下会提供并添加日志记录和异常处理实现。
ExceptionWebSocketHandlerDecorator 捕获所有由任何 WebSocketHandler 方法引发的未捕获异常,并使用状态 1011 关闭 WebSocket 会话,这表示服务器错误。
|
部署
WebSocket API 很容易集成到 Web MVC 应用程序中,其中 DispatcherHandler
既提供 HTTP WebSocket 握手,也提供其他 HTTP 请求服务。
通过调用 WebSocketHttpRequestHandler
,它也很容易集成到其他 HTTP 处理场景中。这非常方便且易于理解。然而,在涉及到 JSR-356 运行时时,需要特别考虑。
Allowed Origins
The default behavior for WebSocket and SockJS is to accept only same-origin requests.
It is also possible to allow all or a specified list of origins.
This check is mostly designed for browser clients.
Nothing prevents other types of clients from modifying the Origin
header value (see
RFC 6454: The Web Origin Concept for more details).
The three possible behaviors are:
-
Allow only same-origin requests (default): In this mode, when SockJS is enabled, the Iframe HTTP response header
X-Frame-Options
is set toSAMEORIGIN
, and JSONP transport is disabled, since it does not allow checking the origin of a request. As a consequence, IE6 and IE7 are not supported when this mode is enabled. -
Allow a specified list of origins: Each allowed origin must start with
http://
orhttps://
. In this mode, when SockJS is enabled, IFrame transport is disabled. As a consequence, IE6 through IE9 are not supported when this mode is enabled. -
Allow all origins: To enable this mode, you should provide
*
as the allowed origin value. In this mode, all transports are available.
You can configure WebSocket and SockJS allowed origins, as the following example shows:
WebSocket 的默认行为是仅接受同源请求。
也可以允许所有或指定的一组来源。
此检查主要设计用于浏览器客户端。
没有任何阻止其他类型的客户端修改 Origin
标头值(有关详细信息,请参见 RFC 6454: Web Origin 概念)。
三种可能的行为是:
-
仅允许同源请求(默认):在此模式下,当启用 SockJS 时,Iframe HTTP 响应头
X-Frame-Options
被设置为SAMEORIGIN
, 并且禁用了 JSONP 传输,因为它不允许检查请求的来源。因此,当启用此模式时,不支持 IE6 和 IE7。 -
允许指定的一组来源:每个允许的来源必须以
http://
或https://
开头。 -
允许所有来源:要启用此模式,应将
*
作为允许的来源值提供。在此模式下,所有传输都可用。
您可以配置 WebSocket 和 SockJS 允许的来源,如下例所示:
@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler")
.setAllowedOrigins("https://mydomain.com");
}
@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}