使用示例
例子来自于官网
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| @Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler");
}
@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}
|
说明:
WebSocketConfigurer
配置 websocket
。
WebSocketHandler
处理 websocket
的连接。
WebSocketServletAutoConfiguration
添加了 tomcat 对 websocket 的支持,也就是 WsSci。
源码位置: org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| @ConditionalOnWebApplication(type = Type.SERVLET)
@AutoConfigureBefore(ServletWebServerFactoryAutoConfiguration.class)
public class WebSocketServletAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Tomcat.class, WsSci.class })
static class TomcatWebSocketConfiguration {
@Bean
@ConditionalOnMissingBean(name = "websocketServletWebServerCustomizer")
TomcatWebSocketServletWebServerCustomizer websocketServletWebServerCustomizer() {
return new TomcatWebSocketServletWebServerCustomizer();
}
}
...
}
|
@EnableWebSocket
最关键的配置入口。
源码位置: org.springframework.web.socket.config.annotation.EnableWebSocket
1
2
3
4
| // 导入 websocket 配置类, 父类为 WebSocketConfigurationSupport
@Import(DelegatingWebSocketConfiguration.class)
public @interface EnableWebSocket {
}
|
源码位置: org.springframework.web.socket.config.annotation.WebSocketConfigurationSupport
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| public class WebSocketConfigurationSupport {
// 注册 WebSocketHandlerMapping
@Bean
public HandlerMapping webSocketHandlerMapping(@Nullable TaskScheduler defaultSockJsTaskScheduler) {
// 初始化 registry
ServletWebSocketHandlerRegistry registry = initHandlerRegistry();
...
// 很重要, 后面继续解析
return registry.getHandlerMapping();
}
private ServletWebSocketHandlerRegistry initHandlerRegistry() {
if (this.handlerRegistry == null) {
this.handlerRegistry = new ServletWebSocketHandlerRegistry();
// 由子类 DelegatingWebSocketConfiguration 来实现
registerWebSocketHandlers(this.handlerRegistry);
}
return this.handlerRegistry;
}
}
|
源码位置: org.springframework.web.socket.config.annotation.ServletWebSocketHandlerRegistry#getHandlerMapping
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| public AbstractHandlerMapping getHandlerMapping() {
Map<String, Object> urlMap = new LinkedHashMap<>();
// 遍历所有的 websocket 的配置
for (ServletWebSocketHandlerRegistration registration : this.registrations) {
// HttpRequestHandler 实现类为 WebSocketHttpRequestHandler,负责处理 websocket 请求, 很重要
MultiValueMap<HttpRequestHandler, String> mappings = registration.getMappings();
mappings.forEach((httpHandler, patterns) -> {
for (String pattern : patterns) {
urlMap.put(pattern, httpHandler);
}
});
}
// WebSocketHandlerMapping 负责拦截 websocket 的 url,然后由 WebSocketHttpRequestHandler 处理请求
WebSocketHandlerMapping hm = new WebSocketHandlerMapping();
hm.setUrlMap(urlMap);
hm.setOrder(this.order);
if (this.urlPathHelper != null) {
hm.setUrlPathHelper(this.urlPathHelper);
}
return hm;
}
|
WebSocketHttpRequestHandler 处理 websocket 请求
源码位置: org.springframework.web.socket.server.support.WebSocketHttpRequestHandler#handleRequest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| @Override
public void handleRequest(HttpServletRequest servletRequest, HttpServletResponse servletResponse)
throws ServletException, IOException {
...
try {
...
// 执行 HandshakeInterceptor#beforeHandshake 方法
if (!chain.applyBeforeHandshake(request, response, attributes)) {
return;
}
// 执行 websocket 握手, 最终会调用 TomcatRequestUpgradeStrategy#upgradeInternal
this.handshakeHandler.doHandshake(request, response, this.wsHandler, attributes);
// 执行 HandshakeInterceptor#afterHandshake 方法
chain.applyAfterHandshake(request, response, null);
}
catch (HandshakeFailureException ex) {
failure = ex;
}
catch (Exception ex) {
failure = new HandshakeFailureException("Uncaught failure for request " + request.getURI(), ex);
}
finally {
...
}
}
|