Polish WebFlux WebSocket docs
Issue: SPR-16820
This commit is contained in:
@@ -71,7 +71,37 @@ Then map it to a URL and add a `WebSocketHandlerAdapter`:
|
||||
[[webflux-websockethandler]]
|
||||
=== WebSocketHandler
|
||||
|
||||
The most basic implementation of a handler is one that handles inbound messages:
|
||||
The `handle` method of `WebSocketHandler` takes `WebSocketSession` and returns `Mono<Void>`
|
||||
to indicate when application handling of the session is complete. The session is handled
|
||||
through two streams, one for inbound and one for outbound messages:
|
||||
|
||||
[options="header"]
|
||||
|===
|
||||
| WebSocketSession method | Description
|
||||
|
||||
| `Flux<WebSocketMessage> receive()`
|
||||
| Provides access to the inbound message stream, and completes when the connection is closed.
|
||||
|
||||
| `Mono<Void> send(Publisher<WebSocketMessage>)`
|
||||
| Takes a source for outgoing messages, writes the messages, and returns a `Mono<Void>` that
|
||||
completes when the source completes and writing is done.
|
||||
|
||||
|===
|
||||
|
||||
A `WebSocketHandler` must compose the inbound and outbound streams into a unified flow, and
|
||||
return a `Mono<Void>` that reflects the completion of that flow. Depending on application
|
||||
requirements, the unified flow completes when:
|
||||
|
||||
* Either inbound or outbound message streams complete.
|
||||
* Inbound stream completes (i.e. connection closed), while outbound is infinite.
|
||||
* At a chosen point through the `close` method of `WebSocketSession`.
|
||||
|
||||
When inbound and outbound message streams are composed together, there is no need to
|
||||
check if the connection is open, since Reactive Streams signals will terminate activity.
|
||||
The inbound stream receives a completion/error signal, and the outbound stream receives
|
||||
receives a cancellation signal.
|
||||
|
||||
The most basic implementation of a handler is one that handles the inbound stream:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
@@ -94,17 +124,44 @@ class ExampleHandler implements WebSocketHandler {
|
||||
<1> Access stream of inbound messages.
|
||||
<2> Do something with each message.
|
||||
<3> Perform nested async operation using message content.
|
||||
<4> Return `Mono<Void>` that doesn't complete while we continue to receive.
|
||||
<4> Return `Mono<Void>` that completes when receiving completes.
|
||||
|
||||
[NOTE]
|
||||
[TIP]
|
||||
====
|
||||
If performing a nested, asynchronous operation, you'll need to call
|
||||
`message.retain()` if the underlying server uses pooled data buffers (e.g. Netty), or
|
||||
otherwise the data buffer may be released before you've had a chance to read the data.
|
||||
For more on this see <<core.adoc#databuffers,Data Buffers and Codecs>>.
|
||||
For nested, asynchronous operations, you may need to call `message.retain()` on underlying
|
||||
servers that use pooled data buffers (e.g. Netty), or otherwise the data buffer may be
|
||||
released before you've had a chance to read the data. For more background see
|
||||
<<core.adoc#databuffers,Data Buffers and Codecs>>.
|
||||
====
|
||||
|
||||
A handler can work with inbound and outbound messages as independent streams:
|
||||
The below implementation combines the inbound with the outbound streams:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
class ExampleHandler implements WebSocketHandler {
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(WebSocketSession session) {
|
||||
|
||||
Flux<WebSocketMessage> output = session.receive() <1>
|
||||
.doOnNext(message -> {
|
||||
// ...
|
||||
})
|
||||
.concatMap(message -> {
|
||||
// ...
|
||||
})
|
||||
.map(value -> session.textMessage("Echo " + value)); <2>
|
||||
|
||||
return session.send(output); <3>
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Handle inbound message stream.
|
||||
<2> Create outbound message, producing a combined flow.
|
||||
<3> Return `Mono<Void>` that doesn't complete while we continue to receive.
|
||||
|
||||
Inbound and outbound streams can be independent, and joined only for completion:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
@@ -134,33 +191,6 @@ class ExampleHandler implements WebSocketHandler {
|
||||
<2> Send outgoing messages.
|
||||
<3> Join the streams and return `Mono<Void>` that completes when _either_ stream ends.
|
||||
|
||||
A handler can compose a connected flow of inbound and outbound messages:
|
||||
4
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
class ExampleHandler implements WebSocketHandler {
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(WebSocketSession session) {
|
||||
|
||||
Flux<WebSocketMessage> output = session.receive() <1>
|
||||
.doOnNext(message -> {
|
||||
// ...
|
||||
})
|
||||
.concatMap(message -> {
|
||||
// ...
|
||||
})
|
||||
.map(value -> session.textMessage("Echo " + value)); <2>
|
||||
|
||||
return session.send(output); <3>
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Handle inbound message stream.
|
||||
<2> Create outbound message, producing a combined flow.
|
||||
<3> Return `Mono<Void>` that doesn't complete while we continue to receive.
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-server-handshake]]
|
||||
@@ -172,6 +202,8 @@ of `HandshakeWebSocketService`, which performs basic checks on the WebSocket req
|
||||
then uses `RequestUpgradeStrategy` for the server in use. Currently there is built-in
|
||||
support for Reactor Netty, Tomcat, Jetty, and Undertow.
|
||||
|
||||
The above are just 3 examples to serve as a starting point.
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-server-config]]
|
||||
|
||||
Reference in New Issue
Block a user