@@ -20,10 +20,10 @@ server side applications that handle WebSocket messages.
20
20
21
21
22
22
[[webflux-websocket-server-handler]]
23
- === WebSocketHandler
23
+ === Server
24
24
[.small]#<<web.adoc#websocket-server-handler,Same in Servlet stack>>#
25
25
26
- Creating a WebSocket server is as simple as implementing `WebSocketHandler`:
26
+ To create a WebSocket server, first create a `WebSocketHandler`:
27
27
28
28
[source,java,indent=0]
29
29
[subs="verbatim,quotes"]
@@ -40,10 +40,7 @@ Creating a WebSocket server is as simple as implementing `WebSocketHandler`:
40
40
}
41
41
----
42
42
43
- Spring WebFlux provides a `WebSocketHandlerAdapter` that can adapt WebSocket
44
- requests and use the above handler to handle the resulting WebSocket session. After the
45
- adapter is registered as a bean, you can map requests to your handler, for example using
46
- `SimpleUrlHandlerMapping`. This is shown below:
43
+ Then map it to a URL and add a `WebSocketHandlerAdapter`:
47
44
48
45
[source,java,indent=0]
49
46
[subs="verbatim,quotes"]
@@ -71,17 +68,109 @@ adapter is registered as a bean, you can map requests to your handler, for examp
71
68
72
69
73
70
71
+ [[webflux-websockethandler]]
72
+ === WebSocketHandler
73
+
74
+ The most basic implementation of a handler is one that handles inbound messages:
75
+
76
+ [source,java,indent=0]
77
+ [subs="verbatim,quotes"]
78
+ ----
79
+ class ExampleHandler implements WebSocketHandler {
80
+
81
+ @Override
82
+ public Mono<Void> handle(WebSocketSession session) {
83
+ return session.receive() <1>
84
+ .doOnNext(message -> {
85
+ // ... <2>
86
+ })
87
+ .concatMap(message -> {
88
+ // ... <3>
89
+ })
90
+ .then(); <4>
91
+ }
92
+ }
93
+ ----
94
+ <1> Access stream of inbound messages.
95
+ <2> Do something with each message.
96
+ <3> Perform nested async operation using message content.
97
+ <4> Return `Mono<Void>` that doesn't complete while we continue to receive.
98
+
99
+ [NOTE]
100
+ ====
101
+ If performing a nested, asynchronous operation, you'll need to call
102
+ `message.retain()` if the underlying server uses pooled data buffers (e.g. Netty), or
103
+ otherwise the data buffer may be released before you've had a chance to read the data.
104
+ For more on this see <<core.adoc#databuffers,Data Buffers and Codecs>>.
105
+ ====
106
+
107
+ A handler can work with inbound and outbound messages as independent streams:
108
+
109
+ [source,java,indent=0]
110
+ [subs="verbatim,quotes"]
111
+ ----
112
+ class ExampleHandler implements WebSocketHandler {
113
+
114
+ @Override
115
+ public Mono<Void> handle(WebSocketSession session) {
116
+
117
+ Mono<Void> input = session.receive() <1>
118
+ .doOnNext(message -> {
119
+ // ...
120
+ })
121
+ .concatMap(message -> {
122
+ // ...
123
+ })
124
+ .then();
125
+
126
+ Flux<String> source = ... ;
127
+ Mono<Void> output = session.send(source.map(session::textMessage)); <2>
128
+
129
+ return Mono.zip(input, output).then(); <3>
130
+ }
131
+ }
132
+ ----
133
+ <1> Handle inbound message stream.
134
+ <2> Send outgoing messages.
135
+ <3> Join the streams and return `Mono<Void>` that completes when _either_ stream ends.
136
+
137
+ A handler can compose a connected flow of inbound and outbound messages:
138
+ 4
139
+ [source,java,indent=0]
140
+ [subs="verbatim,quotes"]
141
+ ----
142
+ class ExampleHandler implements WebSocketHandler {
143
+
144
+ @Override
145
+ public Mono<Void> handle(WebSocketSession session) {
146
+
147
+ Flux<WebSocketMessage> output = session.receive() <1>
148
+ .doOnNext(message -> {
149
+ // ...
150
+ })
151
+ .concatMap(message -> {
152
+ // ...
153
+ })
154
+ .map(value -> session.textMessage("Echo " + value)); <2>
155
+
156
+ return session.send(output); <3>
157
+ }
158
+ }
159
+ ----
160
+ <1> Handle inbound message stream.
161
+ <2> Create outbound message, producing a combined flow.
162
+ <3> Return `Mono<Void>` that doesn't complete while we continue to receive.
163
+
164
+
165
+
74
166
[[webflux-websocket-server-handshake]]
75
- === WebSocket Handshake
167
+ === Handshake
76
168
[.small]#<<web.adoc#websocket-server-handshake,Same in Servlet stack>>#
77
169
78
- `WebSocketHandlerAdapter` does not perform WebSocket handshakes itself. Instead it
79
- delegates to an instance of `WebSocketService`. The default `WebSocketService`
80
- implementation is `HandshakeWebSocketService`.
81
-
82
- The `HandshakeWebSocketService` performs basic checks on the WebSocket request and
83
- delegates to a server-specific `RequestUpgradeStrategy`. At present upgrade strategies
84
- exist for Reactor Netty, Tomcat, Jetty, and Undertow.
170
+ `WebSocketHandlerAdapter` delegates to a `WebSocketService`. By default that's an instance
171
+ of `HandshakeWebSocketService`, which performs basic checks on the WebSocket request and
172
+ then uses `RequestUpgradeStrategy` for the server in use. Currently there is built-in
173
+ support for Reactor Netty, Tomcat, Jetty, and Undertow.
85
174
86
175
87
176
@@ -132,7 +221,7 @@ specify CORS settings by URL pattern. If both are specified they're combined via
132
221
133
222
134
223
[[webflux-websocket-client]]
135
- == WebSocketClient
224
+ === Client
136
225
137
226
Spring WebFlux provides a `WebSocketClient` abstraction with implementations for
138
227
Reactor Netty, Tomcat, Jetty, Undertow, and standard Java (i.e. JSR-356).
0 commit comments