提交 3b4c7a40 编写于 作者: R Rossen Stoyanchev

Improve docs on @Controller methods in STOMP section

Issue: SPR-16631
上级 c5631792
...@@ -1205,82 +1205,146 @@ kinds of arguments and return values supported. ...@@ -1205,82 +1205,146 @@ kinds of arguments and return values supported.
[[websocket-stomp-handle-annotations]] [[websocket-stomp-handle-annotations]]
=== Handler methods === Annotated Controllers
The `@MessageMapping` annotation is supported on methods of `@Controller` classes. Applications can use annotated `@Controller` classes to handle messages from clients.
It can be used for mapping methods to message destinations and can also be combined Such classes can declare `@MessageMapping`, `@SubscribeMapping`, and `@ExceptionHandler`
with the type-level `@MessageMapping` for expressing shared mappings across all methods as described next.
annotated methods within a controller.
By default destination mappings are treated as Ant-style, slash-separated, path
patterns, e.g. "/foo*", "/foo/**". etc. They can also contain template variables,
e.g. "/foo/{id}" that can then be referenced via `@DestinationVariable`-annotated
method arguments.
[NOTE] [[websocket-stomp-message-mapping]]
==== `@MessageMapping`
The `@MessageMapping` annotation can be used on methods to route messages based on their
destination. It is supported at the method level as well as at the type level. At type
level `@MessageMapping` is used to express shared mappings across all methods in a
controller.
By default destination mappings are expected to be Ant-style, path patterns, e.g. "/foo*",
"/foo/**". The patterns include support for template variables, e.g. "/foo/{id}", that can
be referenced with `@DestinationVariable` method arguments.
[TIP]
==== ====
Applications can also use dot-separated destinations (vs slash). Applications can choose to switch to a dot-separated destination convention.
See <<websocket-stomp-destination-separator>>. See <<websocket-stomp-destination-separator>>.
==== ====
The following method arguments are supported for `@MessageMapping` methods: `@MessageMapping` methods can have flexible signatures with the following arguments:
* `Message` method argument to get access to the complete message being processed. [cols="1,2", options="header"]
* `@Payload`-annotated argument for access to the payload of a message, converted with |===
a `org.springframework.messaging.converter.MessageConverter`. | Method argument | Description
The presence of the annotation is not required since it is assumed by default.
Payload method arguments annotated with validation annotations (like `@Validated`) will | `Message`
be subject to JSR-303 validation. | For access to the complete message.
* `@Header`-annotated arguments for access to a specific header value along with
type conversion using an `org.springframework.core.convert.converter.Converter` | `MessageHeaders`
if necessary. | For access to the headers within the `Message`.
* `@Headers`-annotated method argument that must also be assignable to `java.util.Map`
for access to all headers in the message. | `MessageHeaderAccessor`, `SimpMessageHeaderAccessor`, `StompHeaderAccessor`
* `MessageHeaders` method argument for getting access to a map of all headers. | For access to the headers via typed accessor methods.
* `MessageHeaderAccessor`, `SimpMessageHeaderAccessor`, or `StompHeaderAccessor`
for access to headers via typed accessor methods. | `@Payload`
* `@DestinationVariable`-annotated arguments for access to template | For access to the payload of the message, converted (e.g. from JSON) via a configured
variables extracted from the message destination. Values will be converted to `MessageConverter`.
the declared method argument type as necessary.
* `java.security.Principal` method arguments reflecting the user logged in at The presence of this annotation is not required since it is assumed by default if no
the time of the WebSocket HTTP handshake. other argument is matched.
A return value from an `@MessageMapping` method will be converted with a Payload arguments may be annotated with `@javax.validation.Valid` or Spring's `@Validated`
`org.springframework.messaging.converter.MessageConverter` and used as the body in order to be automatically validated.
of a new message that is then sent, by default, to the `"brokerChannel"` with
the same destination as the client message but using the prefix `"/topic"` by | `@Header`
default. An `@SendTo` message level annotation can be used to specify any | For access to a specific header value along with type conversion using an
other destination instead. It can also be set a class-level to share a common `org.springframework.core.convert.converter.Converter` if necessary.
| `@Headers`
| For access to all headers in the message. This argument must be assignable to
`java.util.Map`.
| `@DestinationVariable`
| For access to template variables extracted from the message destination.
Values will be converted to the declared method argument type as necessary.
| `java.security.Principal`
| Reflects the user logged in at the time of the WebSocket HTTP handshake.
|===
When an `@MessageMapping` method returns a value, by default the value is serialized to
a payload through a configured `MessageConverter`, and then sent as a `Message` to the
`"brokerChannel"` from where it is broadcast to subscribers. The destination of the
outbound message is the same as that of the inbound message but prefixed with `"/topic"`.
You can use the `@SendTo` method annotation to customize the destination to send
the payload to. `@SendTo` can also be used at the class level to share a default target
destination to send messages to. `@SendToUser` is an variant for sending messages only to
the user associated with a message. See <<websocket-stomp-user-destination>> for details.
The return value from an `@MessageMapping` method may be wrapped with `ListenableFuture`,
`CompletableFuture`, or `CompletionStage` in order to produce the payload asynchronously.
As an alternative to returning a payload from an `@MessageMapping` method you can also
send messages using the `SimpMessagingTemplate`, which is also how return values are
handled under the covers. See <<websocket-stomp-handle-send>>.
[[websocket-stomp-subscribe-mapping]]
==== `@SubscribeMapping`
The `@SubscribeMapping` annotation is used in combination with `@MessageMapping` in order
to narrow the mapping to subscription messages. In such scenarios, the `@MessageMapping`
annotation specifies the destination while `@SubscribeMapping` indicates interest in
subscription messages only.
An `@SubscribeMapping` method is generally no different from any `@MessageMapping`
method with respect to mapping and input arguments. For example you can combine it with a
type-level `@MessageMapping` to express a shared destination prefix, and you can use the
same <<websocket-stomp-message-mapping,method arguments>> as on any @MessageMapping` method.
The key difference with `@SubscribeMapping` is that the return value of the method is
serialized as a payload and sent, not to the "brokerChannel" but to the
"clientOutboundChannel", effectively replying directly to the client rather than
broadcasting through the broker. This is useful for implementing one-off, request-reply
message exchanges, and never holding on to the subscription. A common scenario for this
pattern is application initialization when data must be loaded and presented.
A `@SubscribeMapping` method can also be annotated with `@SendTo` in which case the
return value is sent to the `"brokerChannel"` with the explicitly specified target
destination. destination.
A response message may also be provided asynchronously via a `ListenableFuture`
or `CompletableFuture`/`CompletionStage` return type signature, analogous to
deferred results in an MVC handler method.
A `@SubscribeMapping` annotation can be used to map subscription requests to [[websocket-stomp-exception-handler]]
`@Controller` methods. It is supported on the method level, but can also be ==== `@MessageExceptionHandler`
combined with a type level `@MessageMapping` annotation that expresses shared
mappings across all message handling methods within the same controller.
By default the return value from an `@SubscribeMapping` method is sent as a An application can use `@MessageExceptionHandler` methods to handle exceptions from
message directly back to the connected client and does not pass through the `@MessageMapping` methods. Exceptions of interest can be declared in the annotation
broker. This is useful for implementing request-reply message interactions; for itself, or through a method argument if you want to get access to the exception instance:
example, to fetch application data when the application UI is being initialized.
Or alternatively an `@SubscribeMapping` method can be annotated with `@SendTo`
in which case the resulting message is sent to the `"brokerChannel"` using
the specified target destination.
[NOTE] [source,java,indent=0]
==== [subs="verbatim,quotes"]
In some cases a controller may need to be decorated with an AOP proxy at runtime. ----
One example is if you choose to have `@Transactional` annotations directly on the @Controller
controller. When this is the case, for controllers specifically, we recommend public class MyController {
using class-based proxying. This is typically the default choice with controllers.
However if a controller must implement an interface that is not a Spring Context // ...
callback (e.g. `InitializingBean`, `*Aware`, etc), you may need to explicitly
configure class-based proxying. For example with `<tx:annotation-driven />`, @MessageExceptionHandler
change to `<tx:annotation-driven proxy-target-class="true" />`. public ApplicationError handleException(MyException exception) {
==== // ...
return appError;
}
}
----
`@MessageExceptionHandler` methods support flexible method signatures and support the same
method argument types and return values as <<websocket-stomp-message-mapping>> methods.
Typically `@MessageExceptionHandler` methods apply within the `@Controller` class (or
class hierarchy) they are declared in. If you want such methods to apply more globally,
across controllers, you can declare them in a class marked with `@ControllerAdvice`.
This is comparable to <<web.adoc#mvc-ann-controller-advice,similar support>> in Spring MVC.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册