@@ -448,31 +448,21 @@ This can be automated through the use of
448
448
449
449
450
450
[[webflux-web-handler-api]]
451
- === WebHandler
451
+ === WebHandler API
452
452
453
- `HttpHandler` is the lowest level contract for running on different HTTP servers.
454
- On top of that foundation, the WebHandler API provides a slightly higher level, but
455
- still general purpose, set of components that form a chain of
456
- {api-spring-framework}/web/server/WebExceptionHandler.html[WebExceptionHandler's],
457
- {api-spring-framework}/web/server/WebFilter.html[WebFilter's], and a
458
- {api-spring-framework}/web/server/WebHandler.html[WebHandler].
453
+ The WebHandler API is a general purpose, server, web API for processing requests through a
454
+ chain of {api-spring-framework}/web/server/WebExceptionHandler.html[WebExceptionHandler's],
455
+ {api-spring-framework}/web/server/WebFilter.html[WebFilter's], and a target
456
+ {api-spring-framework}/web/server/WebHandler.html[WebHandler]. The chain can be assembled
457
+ with `WebHttpHandlerBuilder` either by adding components to the builder or by having them
458
+ detected from a Spring `ApplicationContext`. The builder returns an
459
+ <<webflux-httphandler>> that can then be used to run on any of the supported servers.
459
460
460
- All WebHandler API components take `ServerWebExchange` as input which goes beyond
461
- `ServerHttpRequest` and `ServerHttpResponse` to provide extra building blocks for
462
- use in web applications such as request attributes, session attributes, access to parsed
463
- form data, multipart data, and more.
464
-
465
- `WebHttpHandlerBuilder` is used to assemble a request processing chain. You can use
466
- methods on the builder to add components manually, or more likely have them detected from
467
- a Spring `ApplicationContext`, with the resulting `HttpHandler` ready to run via a
468
- <<webflux-httphandler,server adapter>>:
469
-
470
- [source,java,indent=0]
471
- [subs="verbatim,quotes"]
472
- ----
473
- ApplicationContext context = ...
474
- HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build()
475
- ----
461
+ While `HttpHandler` aims to be the most minimal contract across HTTP servers, the
462
+ WebHandler API provides essential features commonly used to build web applications.
463
+ For example, the `ServerWebExchange` available to WebHandler API components provides
464
+ access not only to the request and response, but also to request and session attributes,
465
+ access to parsed form data, multipart data, and more.
476
466
477
467
478
468
@@ -488,12 +478,14 @@ The table below lists the components that `WebHttpHandlerBuilder` detects:
488
478
| <any>
489
479
| `WebExceptionHandler`
490
480
| 0..N
491
- | Exception handlers to apply after all ``WebFilter``'s and the target `WebHandler`.
481
+ | Provide handling for exceptions from the chain of ``WebFilter``'s and the target
482
+ `WebHandler`. For more details, see <<webflux-exception-handler>>.
492
483
493
484
| <any>
494
485
| `WebFilter`
495
486
| 0..N
496
- | Filters to invoke before and after the target `WebHandler`.
487
+ | Apply interception style logic to before and after the rest of the filter chain and
488
+ the target `WebHandler`. For more details, see <<webflux-filters>>.
497
489
498
490
| "webHandler"
499
491
| `WebHandler`
@@ -645,9 +637,13 @@ a heartbeat and ignore.
645
637
=== Filters
646
638
[.small]#<<web.adoc#filters,Same in Spring MVC>>#
647
639
648
- As part of the <<webflux-web-handler-api>>, the `spring-web` module provides a number of
649
- `WebFilter` implementations.
640
+ In the <<webflux-web-handler-api>>, a `WebFilter` can be used to apply interception-style
641
+ logic before and after the rest of the processing chain of filters and the target
642
+ `WebHandler`. When using the <<webflux-config>>, registering a `WebFilter` is as simple
643
+ as declaring it as a Spring bean, and optionally expressing precedence via `@Order` on
644
+ the bean declaration or by implementing `Ordered`.
650
645
646
+ The following describe the available `WebFilter` implementations:
651
647
652
648
653
649
[[webflux-filters-forwarded-headers]]
@@ -690,6 +686,37 @@ See the section on <<webflux-cors>> and the <<webflux-cors-webfilter>> for more
690
686
691
687
692
688
689
+ [[webflux-exception-handler]]
690
+ === Exceptions
691
+ [.small]#<<web.adoc#mvc-ann-customer-servlet-container-error-page,Same in Spring MVC>>#
692
+
693
+ In the <<webflux-web-handler-api>>, a `WebExceptionHandler` can be used to to handle
694
+ exceptions from the chain of ``WebFilter``'s and the target `WebHandler`. When using the
695
+ <<webflux-config>>, registering a `WebExceptionHandler` is as simple as declaring it as a
696
+ Spring bean, and optionally expressing precedence via `@Order` on the bean declaration or
697
+ by implementing `Ordered`.
698
+
699
+ Below are the available `WebExceptionHandler` implementations:
700
+
701
+ [cols="1,2", options="header"]
702
+ |===
703
+ | Exception Handler | Description
704
+
705
+ | `ResponseStatusExceptionHandler`
706
+ | Provides handling for exceptions of type
707
+ {api-spring-framework}/web/server/ResponseStatusException.html[ResponseStatusException]
708
+ by setting the response to the HTTP status code of the exception.
709
+
710
+ | `WebFluxResponseStatusExceptionHandler`
711
+ | Extension of `ResponseStatusExceptionHandler` that can also determine the HTTP status
712
+ code an `@ResponseStatus` annotation on any exception.
713
+
714
+ This handler is declared in the <<webflux-config>>.
715
+
716
+ |===
717
+
718
+
719
+
693
720
694
721
[[webflux-dispatcher-handler]]
695
722
== DispatcherHandler
@@ -805,24 +832,60 @@ processing by writing to the response directly or using a view to render.
805
832
[[webflux-resulthandling]]
806
833
=== Result Handling
807
834
808
- When `DispatcherHandler` needs to process the return value from a handler, it finds a
809
- `HandlerResultHandler` that support it and invokes it. The available implementations are
810
- listed below with their default order (all are declared in the <<webflux-config>>):
835
+ The return value from the invocation of a handler, through a `HandlerAdapter`, is wrapped
836
+ as `HandlerResult`, along with some additional context, and passed to the first
837
+ `HandlerResultHandler` that claims support for it. The table below shows the available
838
+ `HandlerResultHandler` implementations all of which are declared in the <<webflux-config>>:
839
+
840
+ [cols="1,2,1", options="header"]
841
+ |===
842
+ | Result Handler Type | Return Values | Default Order
843
+
844
+ | `ResponseEntityResultHandler`
845
+ | `ResponseEntity`, typically from ``@Controller``'s.
846
+ | 0
847
+
848
+ | `ServerResponseResultHandler`
849
+ | `ServerResponse`, typically from functional endpoints.
850
+ | 0
851
+
852
+ | `ResponseBodyResultHandler`
853
+ | Handle return values from `@ResponseBody` methods or `@RestController` classes.
854
+ | 100
855
+
856
+ | `ViewResolutionResultHandler`
857
+ | `CharSequence` or {api-spring-framework}/web/reactive/result/view/View.html[View],
858
+ {api-spring-framework}/ui/Model.html[Model] or `Map`,
859
+ {api-spring-framework}/web/reactive/result/view/Rendering.html[Rendering],
860
+ or any other Object is treated as a model attribute.
861
+
862
+ Also see <<webflux-viewresolution>>.
863
+ | `Integer.MAX_VALUE`
864
+
865
+ |===
866
+
867
+
868
+
869
+ [[webflux-dispatcher-exceptions]]
870
+ === Exceptions
871
+ [.small]#<<web.adoc#mvc-exceptionhandlers,Same in Spring MVC>>#
872
+
873
+ The `HandlerResult` returned from a `HandlerAdapter` may expose a function for error
874
+ handling based on some handler-specific mechanism. This error function is called if:
875
+
876
+ * the handler (e.g. `@Controller`) invocation fails.
877
+ * handling of the handler return value through a `HandlerResultHandler` fails.
811
878
812
- * `ResponseEntityResultHandler` -- handles `ResponseEntity` return values typically
813
- returned from annotated controllers. The order is set to 0 since it safely matches return
814
- values by type.
815
- * `ServerResponseResultHandler` -- supports `ServerResponse` return values typically
816
- returned from functional endpoints. The order is set to 0 since it safely matches return
817
- values by type.
818
- * `ResponseBodyResultHandler` -- handles return values from `@ResponseBody` methods or
819
- `@RestController` classes. The order is set to 100, i.e. after result handlers that
820
- check for a specific type.
821
- * `ViewResolutionResultHandler` -- performs the <<webflux-viewresolution>> algorithm for
822
- HTML template rendering. The order is set to `Ordered.LOWEST_PRECEDENCE` since it
823
- supports several specific types, e.g. `String`, `Map`, `Rendering`, and others, but will
824
- also treat any other Object as a model attribute. This is why it needs to be last in
825
- the order.
879
+ The error function can change the response, e.g. to an error status, as long as an error
880
+ signal occurs before the reactive type returned from the handler produces any data items.
881
+
882
+ This is how `@ExceptionHandler` methods in `@Controller` classes are supported.
883
+ By contrast, support for the same in Spring MVC is built on a `HandlerExceptionResolver`.
884
+ This generally shouldn't matter, however, keep in mind that in WebFlux you cannot use a
885
+ `@ControllerAdvice` to handle exceptions that occur before a handler is chosen.
886
+
887
+ See also <<webflux-ann-controller-exceptions>> in the Annotated Controller section, or
888
+ <<webflux-exception-handler>> in the WebHandler API section.
826
889
827
890
828
891
@@ -2159,15 +2222,19 @@ controller method. Use a composite interface if you need to activate multiple vi
2159
2222
2160
2223
2161
2224
[[webflux-ann-modelattrib-methods]]
2162
- === Model Methods
2225
+ === Model
2163
2226
[.small]#<<web.adoc#mvc-ann-modelattrib-methods,Same in Spring MVC>>#
2164
2227
2165
- The `@ModelAttribute` annotation can be used on `@RequestMapping`
2166
- <<webflux-ann-modelattrib-method-args,method arguments>> to create or access an Object
2167
- from the model and bind it to the request. `@ModelAttribute` can also be used as a
2168
- method-level annotation on controller methods whose purpose is not to handle requests
2169
- but to add commonly needed model attributes prior to request handling.
2228
+ The `@ModelAttribute` annotation can be used:
2229
+
2230
+ * On a <<webflux-ann-modelattrib-method-args,method argument>> in `@RequestMapping` methods
2231
+ to create or access an Object from the model, and to bind it to the request through a
2232
+ `WebDataBinder`.
2233
+ * As a method-level annotation in `@Controller` or `@ControllerAdvice` classes helping
2234
+ to initialize the model prior to any `@RequestMapping` method invocation.
2235
+ * On a `@RequestMapping` method to mark its return value is a model attribute.
2170
2236
2237
+ This section discusses `@ModelAttribute` methods, or the 2nd from the list above.
2171
2238
A controller can have any number of `@ModelAttribute` methods. All such methods are
2172
2239
invoked before `@RequestMapping` methods in the same controller. A `@ModelAttribute`
2173
2240
method can also be shared across controllers via `@ControllerAdvice`. See the section on
@@ -2253,14 +2320,16 @@ as a view name. `@ModelAttribute` can also help to customize the model attribute
2253
2320
2254
2321
2255
2322
[[webflux-ann-initbinder]]
2256
- === Binder Methods
2323
+ === DataBinder
2257
2324
[.small]#<<web.adoc#mvc-ann-initbinder,Same in Spring MVC>>#
2258
2325
2259
- `@InitBinder` methods in an `@Controller` or `@ControllerAdvice` class can be used to
2260
- customize type conversion for method arguments that represent String-based request values
2261
- (e.g. request parameters, path variables, headers, cookies, and others). Type conversion
2262
- also applies during data binding of request parameters onto `@ModelAttribute` arguments
2263
- (i.e. command objects).
2326
+ `@Controller` or `@ControllerAdvice` classes can have `@InitBinder` methods in order to
2327
+ initialize instances of `WebDataBinder`, and those in turn are used to:
2328
+
2329
+ * Bind request parameters (i.e. form data or query) to a model object.
2330
+ * Convert String-based request values such as request parameters, path variables,
2331
+ headers, cookies, and others, to the target type of controller method arguments.
2332
+ * Format model object values as String values when rendering HTML forms.
2264
2333
2265
2334
`@InitBinder` methods can register controller-specific `java.bean.PropertyEditor`, or
2266
2335
Spring `Converter` and `Formatter` components. In addition, the
@@ -2310,6 +2379,73 @@ controller-specific ``Formatter``'s:
2310
2379
2311
2380
2312
2381
2382
+ [[webflux-ann-controller-exceptions]]
2383
+ === Exceptions
2384
+ [.small]#<<web.adoc#mvc-ann-exceptionhandler,Same in Spring MVC>>#
2385
+
2386
+ `@Controller` and <<mvc-ann-controller-advice,@ControllerAdvice>> classes can have
2387
+ `@ExceptionHandler` methods to handle exceptions from controller methods. For example:
2388
+
2389
+ [source,java,indent=0]
2390
+ [subs="verbatim,quotes"]
2391
+ ----
2392
+ @Controller
2393
+ public class SimpleController {
2394
+
2395
+ // ...
2396
+
2397
+ @ExceptionHandler
2398
+ public ResponseEntity<String> handle(IOException ex) {
2399
+ // ...
2400
+ }
2401
+
2402
+ }
2403
+ ----
2404
+
2405
+ The annotation can list the exception types to match. Or simply declare the target
2406
+ exception as a method argument as shown above. When multiple exception methods match,
2407
+ a root exception match is generally preferred to a cause exception match. More formally
2408
+ the `ExceptionDepthComparator` is used to sort exceptions based on their depth from the
2409
+ thrown exception type.
2410
+
2411
+ In a multi-`@ControllerAdvice` arrangement, please declare your primary root exception
2412
+ mappings on a `@ControllerAdvice` prioritized with a corresponding order. While a root
2413
+ exception match is preferred to a cause, this is mainly among the methods of a given
2414
+ controller or `@ControllerAdvice`. That means a cause match on a higher-priority
2415
+ `@ControllerAdvice` is preferred to any match (e.g. root) on a lower-priority
2416
+ `@ControllerAdvice`.
2417
+
2418
+ Support for `@ExceptionHandler` methods in Spring WebFlux is provided by the
2419
+ `HandlerAdapter` for `@RequestMapping` methods. See <<webflux-dispatcher-exceptions>>
2420
+ under the `DispatcherHandler` section for more details.
2421
+
2422
+
2423
+ An `@ExceptionHandler` method in WebFlux supports the same method arguments and return
2424
+ values as an `@RequestMapping` method does with the exception of request body and
2425
+ `@ModelAttribute` related method arguments.
2426
+
2427
+
2428
+ [[webflux-ann-rest-exceptions]]
2429
+ ==== REST API exceptions
2430
+ [.small]#<<web.adoc#mvc-ann-rest-exceptions,Same in Spring MVC>>#
2431
+
2432
+ A common requirement for REST services is to include error details in the body of the
2433
+ response. The Spring Framework does not automatically do this because the representation
2434
+ of error details in the response body is application specific. However a
2435
+ `@RestController` may use `@ExceptionHandler` methods with a `ResponseEntity` return
2436
+ value to set the status and the body of the response. Such methods may also be declared
2437
+ in `@ControllerAdvice` classes to apply them globally.
2438
+
2439
+ [NOTE]
2440
+ ====
2441
+ Note that Spring WebFlux does not have an equivalent for the Spring MVC
2442
+ `ResponseEntityExceptionHandler` because WebFlux only raises `ResponseStatusException`
2443
+ (or sub-classes of), which and those do not need to be translated translation to an HTTP
2444
+ status code.
2445
+ ====
2446
+
2447
+
2448
+
2313
2449
[[webflux-ann-controller-advice]]
2314
2450
=== Controller Advice
2315
2451
[.small]#<<web.adoc#mvc-ann-controller-advice,Same in Spring MVC>>#
0 commit comments