@@ -306,32 +306,31 @@ libraries, refer to their respective documentation.
306
306
307
307
308
308
[[webflux-reactive-spring-web]]
309
- == Reactive Spring Web
309
+ == Reactive Core
310
310
311
- The `spring-web` module provides low level infrastructure and HTTP abstractions -- client
312
- and server, to build reactive web applications. All public APIs are built around Reactive
313
- Streams with Reactor as a backing implementation.
311
+ The `spring-web` module contains abstractions and infrastructure to build reactive web
312
+ applications. For server side processing this is organized in two distinct levels:
314
313
315
- Server support is organized in two layers:
314
+ * <<webflux-httphandler,HttpHandler>> -- basic, common API for HTTP request handling with
315
+ non-blocking I/O and (Reactive Streams) back pressure, along with adapters for each
316
+ supported server.
317
+ * <<webflux-web-handler-api>> -- slightly higher level, but still general purpose API for
318
+ server request handling, which underlies higher level programming models such as annotated
319
+ controllers and functional endpoints.
316
320
317
- * <<webflux-httphandler,HttpHandler>> and server adapters -- the most basic, common API
318
- for HTTP request handling with Reactive Streams back pressure.
319
- * <<webflux-web-handler-api>> -- slightly higher level but still general
320
- purpose server web API with filter chain style processing.
321
+ The reactive core also includes <<webflux-codecs>> for client and server side use.
321
322
322
323
323
324
324
325
[[webflux-httphandler]]
325
326
=== HttpHandler
326
327
327
- Every HTTP server has some API for HTTP request handling.
328
328
{api-spring-framework}/http/server/reactive/HttpHandler.html[HttpHandler]
329
- is a simple contract with one method to handle a request and response.
330
- It is intentionally minimal. Its main purpose is to provide a common, Reactive Streams
331
- based API for HTTP request handling over different servers .
329
+ is a simple contract with a single method to handle a request and response. It is
330
+ intentionally minimal as its main purpose is to provide an abstraction over different
331
+ server APIs for HTTP request handling.
332
332
333
- The `spring-web` module contains adapters for every supported server. The table below shows
334
- the server APIs are used and where Reactive Streams support comes from:
333
+ Supported server APIs:
335
334
336
335
[cols="1,2,2", options="header"]
337
336
|===
@@ -358,9 +357,8 @@ the server APIs are used and where Reactive Streams support comes from:
358
357
| spring-web: Servlet 3.1 non-blocking I/O to Reactive Streams bridge
359
358
|===
360
359
361
- Here are required dependencies,
362
- https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-the-Spring-Framework[supported versions],
363
- and code snippets for each server:
360
+ Server dependencies (and
361
+ https://github.com/spring-projects/spring-framework/wiki/What%27s-New-in-the-Spring-Framework[supported versions]):
364
362
365
363
|===
366
364
|Server name|Group id|Artifact name
@@ -382,7 +380,9 @@ and code snippets for each server:
382
380
|jetty-server, jetty-servlet
383
381
|===
384
382
385
- Reactor Netty:
383
+ Code snippets to adapt `HttpHandler` to each server API:
384
+
385
+ *Reactor Netty*
386
386
[source,java,indent=0]
387
387
[subs="verbatim,quotes"]
388
388
----
@@ -391,7 +391,7 @@ ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
391
391
HttpServer.create(host, port).newHandler(adapter).block();
392
392
----
393
393
394
- Undertow:
394
+ * Undertow*
395
395
[source,java,indent=0]
396
396
[subs="verbatim,quotes"]
397
397
----
@@ -401,7 +401,7 @@ Undertow server = Undertow.builder().addHttpListener(port, host).setHandler(adap
401
401
server.start();
402
402
----
403
403
404
- Tomcat:
404
+ * Tomcat*
405
405
[source,java,indent=0]
406
406
[subs="verbatim,quotes"]
407
407
----
@@ -418,7 +418,7 @@ server.setPort(port);
418
418
server.start();
419
419
----
420
420
421
- Jetty:
421
+ * Jetty*
422
422
[source,java,indent=0]
423
423
[subs="verbatim,quotes"]
424
424
----
@@ -437,23 +437,22 @@ server.addConnector(connector);
437
437
server.start();
438
438
----
439
439
440
- [NOTE]
441
- ====
442
- To deploy as a WAR to a Servlet 3.1+ container, wrap `HttpHandler` with
443
- `ServletHttpHandlerAdapter` and register that as a `Servlet`.
444
- This can be automated through the use of
445
- {api-spring-framework}/web/server/adapter/AbstractReactiveWebInitializer.html[AbstractReactiveWebInitializer].
446
- ====
440
+ *Servlet 3.1+ Container*
441
+
442
+ To deploy as a WAR to any Servlet 3.1+ container, simply extend and include
443
+ {api-spring-framework}/web/server/adapter/AbstractReactiveWebInitializer.html[AbstractReactiveWebInitializer]
444
+ in the WAR, which wraps an `HttpHandler` with `ServletHttpHandlerAdapter` and registers
445
+ that as a `Servlet`.
447
446
448
447
449
448
450
449
[[webflux-web-handler-api]]
451
450
=== WebHandler API
452
451
453
452
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
453
+ chain of {api-spring-framework}/web/server/WebExceptionHandler.html[WebExceptionHandler],
454
+ {api-spring-framework}/web/server/WebFilter.html[WebFilter], and a target
455
+ {api-spring-framework}/web/server/WebHandler.html[WebHandler] components . The chain can be assembled
457
456
with `WebHttpHandlerBuilder` either by adding components to the builder or by having them
458
457
detected from a Spring `ApplicationContext`. The builder returns an
459
458
<<webflux-httphandler>> that can then be used to run on any of the supported servers.
@@ -555,84 +554,6 @@ content to `Flux<Part>` without collecting to a `MultiValueMap`.
555
554
556
555
557
556
558
- [[webflux-codecs]]
559
- === Message Codecs
560
- [.small]#<<integration.adoc#rest-message-conversion,Same in Spring MVC>>#
561
-
562
- The `spring-web` module defines the
563
- {api-spring-framework}/http/codec/HttpMessageReader.html[HttpMessageReader] and
564
- {api-spring-framework}/http/codec/HttpMessageWriter.html[HttpMessageWriter] contracts
565
- for encoding and decoding the body of HTTP requests and responses via Rective Streams
566
- ``Publisher``'s. These contacts are used on the client side, e.g. in the `WebClient`,
567
- and on the server side, e.g. in annotated controllers and functional endpoints.
568
-
569
- The `spring-core` module defines the
570
- {api-spring-framework}/core/codec/Encoder.html[Encoder] and
571
- {api-spring-framework}/core/codec/Decoder.html[Decoder] contracts that are independent of
572
- HTTP and rely on the {api-spring-framework}/core/io/buffer/DataBuffer.html[DataBuffer]
573
- contract that abstracts different byte buffer representations such as the Netty `ByteBuf`
574
- and `java.nio.ByteBuffer` (see <<core#databuffers, Data Buffers and Codecs>>).
575
- An `Encoder` can be wrapped with `EncoderHttpMessageWriter` to be used as an
576
- `HttpMessageWriter` while a `Decoder` can be wrapped with `DecoderHttpMessageReader` to
577
- be used as an `HttpMessageReader`.
578
-
579
- The `spring-core` module contains basic `Encoder` and `Decoder` implementations for
580
- `byte[]`, `ByteBuffer`, `DataBuffer`, `Resource`, and `String`. The `spring-web` module
581
- adds ``Encoder``'s and ``Decoder``'s for Jackson JSON, Jackson Smile, and JAXB2.
582
- The `spring-web` module also contains some web-specific readers and writers for
583
- server-sent events, form data, and multipart requests.
584
-
585
- To configure or customize the readers and writers to use, applications will typically use
586
- `ClientCodecConfigurer` or `ServerCodecConfigurer`.
587
-
588
-
589
- [[webflux-codecs-jackson]]
590
- ==== Jackson
591
-
592
- The decoder relies on Jackson's non-blocking, byte array parser to parse a stream of byte
593
- chunks into a `TokenBuffer` stream, which can then be turned into Objects with Jackson's
594
- `ObjectMapper`. JSON and https://github.com/FasterXML/smile-format-specification[Smile]
595
- (binary JSON) data formats are currently supported.
596
-
597
- The encoder processes a `Publisher<?>` as follows:
598
-
599
- * if the `Publisher` is a `Mono` (i.e. single value), the value is encoded when available.
600
- * if media type is `application/stream+json` for JSON or `application/stream+x-jackson-smile`
601
- for Smile, each value produced by the `Publisher` is encoded individually (and followed
602
- by a new line in JSON).
603
- * otherwise all items from the `Publisher` are gathered in with `Flux#collectToList()`
604
- and the resulting collection is encoded as an array.
605
-
606
- As a special case to the above rules the `ServerSentEventHttpMessageWriter` feeds items
607
- emitted from its input `Publisher` individually into the `Jackson2JsonEncoder` as a
608
- `Mono<?>`.
609
-
610
- Note that both the Jackson JSON encoder and decoder explicitly back out of rendering
611
- elements of type `String`. Instead ``String``'s are treated as low level content, (i.e.
612
- serialized JSON) and are rendered as-is by the `CharSequenceEncoder`. If you want a
613
- `Flux<String>` rendered as a JSON array, you'll have to use `Flux#collectToList()` and
614
- provide a `Mono<List<String>>` instead.
615
-
616
-
617
- [[webflux-codecs-streaming]]
618
- ==== HTTP Streaming
619
- [.small]#<<web.adoc#mvc-ann-async-http-streaming,Same in Spring MVC>>#
620
-
621
- When a multi-value, reactive type such as `Flux` is used for response rendering, it may
622
- be collected to a `List` and rendered as a whole (e.g. JSON array), or it may be treated
623
- as an infinite stream with each item flushed immediately. The determination for which is
624
- which is made based on content negotiation and the selected media type which may imply a
625
- streaming format (e.g. "text/event-stream", "application/stream+json"), or not
626
- (e.g. "application/json").
627
-
628
- When streaming to the HTTP response, regardless of the media type (e.g. text/event-stream,
629
- application/stream+json), it is important to send data periodically, since the write would
630
- fail if the client has disconnected. The send could take the form of an empty
631
- (comment-only) SSE event, or any other data that the other side would have to interpret as
632
- a heartbeat and ignore.
633
-
634
-
635
-
636
557
[[webflux-filters]]
637
558
=== Filters
638
559
[.small]#<<web.adoc#filters,Same in Spring MVC>>#
@@ -717,6 +638,80 @@ Below are the available `WebExceptionHandler` implementations:
717
638
718
639
719
640
641
+ [[webflux-codecs]]
642
+ === Codecs
643
+ [.small]#<<integration.adoc#rest-message-conversion,Same in Spring MVC>>#
644
+
645
+ {api-spring-framework}/http/codec/HttpMessageReader.html[HttpMessageReader] and
646
+ {api-spring-framework}/http/codec/HttpMessageWriter.html[HttpMessageWriter] are contracts
647
+ for encoding and decoding HTTP request and response content via non-blocking I/O with
648
+ (Rective Streams) back pressure.
649
+
650
+ {api-spring-framework}/core/codec/Encoder.html[Encoder] and
651
+ {api-spring-framework}/core/codec/Decoder.html[Decoder] are contracts for encoding and
652
+ decoding content, independent of HTTP. They can be wrapped with `EncoderHttpMessageWriter`
653
+ or `DecoderHttpMessageReader` and used for web processing.
654
+
655
+ All codecs are for client or server side use. All build on
656
+ {api-spring-framework}/core/io/buffer/DataBuffer.html[DataBuffer] which abstracts byte
657
+ buffer representations such as the Netty `ByteBuf` or `java.nio.ByteBuffer` (see
658
+ <<core#databuffers, Data Buffers and Codecs>> for more details). `ClientCodecConfigurer`
659
+ and `ServerCodecConfigurer` are typically used to configure and customize the codecs to
660
+ use in an application.
661
+
662
+ The `spring-core` module has encoders and decoders for `byte[]`, `ByteBuffer`, `DataBuffer`,
663
+ `Resource`, and `String`. The `spring-web` module adds encoders and decoders for Jackson
664
+ JSON, Jackson Smile, JAXB2, along with other web-specific HTTP message readers and writers
665
+ for form data, multipart requests, and server-sent events.
666
+
667
+
668
+ [[webflux-codecs-jackson]]
669
+ ==== Jackson
670
+
671
+ The decoder relies on Jackson's non-blocking, byte array parser to parse a stream of byte
672
+ chunks into a `TokenBuffer` stream, which can then be turned into Objects with Jackson's
673
+ `ObjectMapper`. JSON and https://github.com/FasterXML/smile-format-specification[Smile]
674
+ (binary JSON) data formats are currently supported.
675
+
676
+ The encoder processes a `Publisher<?>` as follows:
677
+
678
+ * if the `Publisher` is a `Mono` (i.e. single value), the value is encoded when available.
679
+ * if media type is `application/stream+json` for JSON or `application/stream+x-jackson-smile`
680
+ for Smile, each value produced by the `Publisher` is encoded individually (and followed
681
+ by a new line in JSON).
682
+ * otherwise all items from the `Publisher` are gathered in with `Flux#collectToList()`
683
+ and the resulting collection is encoded as an array.
684
+
685
+ As a special case to the above rules the `ServerSentEventHttpMessageWriter` feeds items
686
+ emitted from its input `Publisher` individually into the `Jackson2JsonEncoder` as a
687
+ `Mono<?>`.
688
+
689
+ Note that both the Jackson JSON encoder and decoder explicitly back out of rendering
690
+ elements of type `String`. Instead ``String``'s are treated as low level content, (i.e.
691
+ serialized JSON) and are rendered as-is by the `CharSequenceEncoder`. If you want a
692
+ `Flux<String>` rendered as a JSON array, you'll have to use `Flux#collectToList()` and
693
+ provide a `Mono<List<String>>` instead.
694
+
695
+
696
+ [[webflux-codecs-streaming]]
697
+ ==== HTTP Streaming
698
+ [.small]#<<web.adoc#mvc-ann-async-http-streaming,Same in Spring MVC>>#
699
+
700
+ When a multi-value, reactive type such as `Flux` is used for response rendering, it may
701
+ be collected to a `List` and rendered as a whole (e.g. JSON array), or it may be treated
702
+ as an infinite stream with each item flushed immediately. The determination for which is
703
+ which is made based on content negotiation and the selected media type which may imply a
704
+ streaming format (e.g. "text/event-stream", "application/stream+json"), or not
705
+ (e.g. "application/json").
706
+
707
+ When streaming to the HTTP response, regardless of the media type (e.g. text/event-stream,
708
+ application/stream+json), it is important to send data periodically, since the write would
709
+ fail if the client has disconnected. The send could take the form of an empty
710
+ (comment-only) SSE event, or any other data that the other side would have to interpret as
711
+ a heartbeat and ignore.
712
+
713
+
714
+
720
715
721
716
[[webflux-dispatcher-handler]]
722
717
== DispatcherHandler
@@ -2532,6 +2527,11 @@ Javadoc for more details.
2532
2527
2533
2528
2534
2529
2530
+ include::webflux-functional.adoc[leveloffset=+1]
2531
+
2532
+
2533
+
2534
+
2535
2535
[[webflux-uri-building]]
2536
2536
== URI Links
2537
2537
[.small]#<<web.adoc#mvc-uri-building,Same in Spring MVC>>#
@@ -2544,11 +2544,6 @@ include::web-uris.adoc[leveloffset=+2]
2544
2544
2545
2545
2546
2546
2547
- include::webflux-functional.adoc[leveloffset=+1]
2548
-
2549
-
2550
-
2551
-
2552
2547
include::webflux-cors.adoc[leveloffset=+1]
2553
2548
2554
2549
0 commit comments