|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2021 the original author or authors. |
| 2 | + * Copyright 2002-2025 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
23 | 23 | import reactor.core.publisher.Mono;
|
24 | 24 |
|
25 | 25 | /**
|
26 |
| - * Handler for a WebSocket session. |
27 |
| - * |
28 |
| - * <p>A server {@code WebSocketHandler} is mapped to requests with |
| 26 | + * Handler for a WebSocket messages. You can use it as follows: |
| 27 | + * <ul> |
| 28 | + * <li>On the server side, {@code WebSocketHandler} is mapped to requests with |
29 | 29 | * {@link org.springframework.web.reactive.handler.SimpleUrlHandlerMapping
|
30 | 30 | * SimpleUrlHandlerMapping} and
|
31 | 31 | * {@link org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter
|
32 |
| - * WebSocketHandlerAdapter}. A client {@code WebSocketHandler} is passed to the |
| 32 | + * WebSocketHandlerAdapter}. |
| 33 | + * <li>On the client side, {@code WebSocketHandler} is passed into the |
33 | 34 | * {@link org.springframework.web.reactive.socket.client.WebSocketClient
|
34 | 35 | * WebSocketClient} execute method.
|
| 36 | + * </ul> |
35 | 37 | *
|
36 |
| - * <p>Use {@link WebSocketSession#receive() session.receive()} to compose on |
37 |
| - * the inbound message stream, and {@link WebSocketSession#send(Publisher) |
38 |
| - * session.send(publisher)} for the outbound message stream. Below is an |
39 |
| - * example, combined flow to process inbound and to send outbound messages: |
| 38 | + * <p>{@link WebSocketSession#receive() session.receive()} handles inbound |
| 39 | + * messages, while {@link WebSocketSession#send(Publisher) session.send} |
| 40 | + * sends outbound messages. Below is an example of handling inbound messages |
| 41 | + * and responding to every message: |
40 | 42 | *
|
41 | 43 | * <pre class="code">
|
42 |
| - * class ExampleHandler implements WebSocketHandler { |
43 |
| - * |
44 |
| - * @Override |
45 |
| - * public Mono<Void> handle(WebSocketSession session) { |
46 |
| - * |
47 |
| - * Flux<WebSocketMessage> output = session.receive() |
48 |
| - * .doOnNext(message -> { |
49 |
| - * // This is for side effects such as |
50 |
| - * // - Logging incoming messages |
51 |
| - * // - Updating some metrics or counters |
52 |
| - * // - Performing access checks or validations (non-blocking) |
53 |
| - * System.out.println("Got message: " + message.getPayloadAsText()); |
54 |
| - * }) |
55 |
| - * .concatMap(message -> { |
56 |
| - * // This is where you handle the actual processing of the incoming message. It |
57 |
| - * // might involve: |
58 |
| - * // - Parsing the message content (e.g., JSON parsing) |
59 |
| - * // - Invoking a reactive service (e.g., database, HTTP call, etc.) |
60 |
| - * // - Returning a transformed value, typically a Mono<String> or Mono<SomeType> |
61 |
| - * // if you're mapping to another data format |
62 |
| - * return Mono.just(message.getPayloadAsText()); |
63 |
| - * }) |
64 |
| - * .map(value -> { |
65 |
| - * // This is where you produce one or more responses for the message |
66 |
| - * return session.textMessage("Echo " + value)); |
67 |
| - * }); |
68 |
| - * |
69 |
| - * return session.send(output); |
70 |
| - * } |
71 |
| - * } |
| 44 | + * class ExampleHandler implements WebSocketHandler { |
| 45 | + * |
| 46 | + * @Override |
| 47 | + * public Mono<Void> handle(WebSocketSession session) { |
| 48 | + * Flux<WebSocketMessage> output = session.receive() |
| 49 | + * .doOnNext(message -> { |
| 50 | + * // Imperative calls without a return value: |
| 51 | + * // perform access checks, log, validate, update metrics. |
| 52 | + * // ... |
| 53 | + * }) |
| 54 | + * .concatMap(message -> { |
| 55 | + * // Async, non-blocking calls: |
| 56 | + * // parse messages, call a database, make remote calls. |
| 57 | + * // Return the same message, or a transformed value |
| 58 | + * // ... |
| 59 | + * }); |
| 60 | + * return session.send(output); |
| 61 | + * } |
| 62 | + * } |
72 | 63 | * </pre>
|
73 | 64 | *
|
74 | 65 | * <p>If processing inbound and sending outbound messages are independent
|
75 | 66 | * streams, they can be joined together with the "zip" operator:
|
76 | 67 | *
|
77 | 68 | * <pre class="code">
|
78 |
| - * class ExampleHandler implements WebSocketHandler { |
79 |
| - * |
80 |
| - * @Override |
81 |
| - * public Mono<Void> handle(WebSocketSession session) { |
82 |
| - * |
83 |
| - * Mono<Void> input = session.receive() |
84 |
| - * .doOnNext(message -> { |
85 |
| - * // ... |
86 |
| - * }) |
87 |
| - * .concatMap(message -> { |
88 |
| - * // ... |
89 |
| - * }) |
90 |
| - * .then(); |
91 |
| - * |
92 |
| - * Flux<String> source = ... ; |
93 |
| - * Mono<Void> output = session.send(source.map(session::textMessage)); |
94 |
| - * |
95 |
| - * return Mono.zip(input, output).then(); |
96 |
| - * } |
97 |
| - * } |
| 69 | + * class ExampleHandler implements WebSocketHandler { |
| 70 | + * |
| 71 | + * @Override |
| 72 | + * public Mono<Void> handle(WebSocketSession session) { |
| 73 | + * |
| 74 | + * Mono<Void> input = session.receive() |
| 75 | + * .doOnNext(message -> { |
| 76 | + * // ... |
| 77 | + * }) |
| 78 | + * .concatMap(message -> { |
| 79 | + * // ... |
| 80 | + * }) |
| 81 | + * .then(); |
| 82 | + * |
| 83 | + * Flux<String> source = ... ; |
| 84 | + * Mono<Void> output = session.send(source.map(session::textMessage)); |
| 85 | + * |
| 86 | + * return Mono.zip(input, output).then(); |
| 87 | + * } |
| 88 | + * } |
98 | 89 | * </pre>
|
99 | 90 | *
|
100 | 91 | * <p>A {@code WebSocketHandler} must compose the inbound and outbound streams
|
|
0 commit comments