Add chapter on Spring Web Reactive support

Issue: SPR-14497
This commit is contained in:
Rossen Stoyanchev 2016-07-25 18:33:43 -04:00
parent af4415e1ba
commit 5cf8b695cb
3 changed files with 198 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -0,0 +1,196 @@
[[web-reactive]]
= Web Reactive Framework
This section provides basic information on the Spring Web Reactive support in Spring Framework 5.
[[web-reactive-intro]]
== Introduction
[[web-reactive-programming]]
=== Reactive Programming
In plain terms reactive programming is about non-blocking applications that are asynchronous
and event-driven and require a small number of threads to scale. A key aspect of that
definition is the concept of backpressure which is a mechanism to ensures producers
don't overwhelm consumers. For example in a pipeline of reactive components that extends
from the database to the HTTP server when an HTTP connection slows down the data
repository slows down as well or stops until capacity frees up.
Reactive programming involves a shift from imperative to declarative, async composition
of logic. This is comparable to how `CompletableFuture` in Java 8 allows declaring
follow-up actions in lambda expressions to be executed when the future completes.
A proper introduction to Reactive programming is beyond scope of this documentation.
For a more extended introduction check the excellent multi-part series
https://spring.io/blog/2016/06/07/notes-on-reactive-programming-part-i-the-reactive-landscape["Notes on Reactive Programming"]
by Dave Syer.
[[web-reactive-api]]
=== Spring Web Reactive Types
Spring Framework 5 embraces
https://github.com/reactive-streams/reactive-streams-jvm#reactive-streams[Reactive Streams]
as the contract for communicating backpressure across async components and
libraries. Reactive Streams is the result of an industry collaboration and is also
adopted in Java 9 as `java.util.concurrent.Flow`.
For its own reactive support the Spring Framework relies on
https://projectreactor.io/[Reactor] which implements Reactive Streams and extends
the Reactive Streams `Publisher` contract with the `Flux` and `Mono` composable API
types that provide declarative operations on data sequence of `0..N` and `0..1`.
The Spring Framework exposes `Flux` and `Mono` in many of its reactive APIs.
At the application level however as always Spring provides choice and fully supports
the use of RxJava. For more on reactive types check the blog post
https://spring.io/blog/2016/04/19/understanding-reactive-types["Understanding Reactive Types"]
by Sebastien Deleuze.
[[web-reactive-feature-overview]]
== Spring Reactive Web Overview
[[web-reactive-module]]
=== Spring Web Reactive Module
Spring Framework 5 adds a new `spring-web-reactive` module that supports the same
`@Controller` and `@RestController` programming model as Spring MVC but executed
on a reactive and non-blocking foundation. The diagram below shows how Spring MVC
and Spring Web Reactive side by side:
image::images/web-reactive-overview.png[width=720]
Spring Web Reactive makes use of the Servlet 3.1 non-blocking I/O API and runs on
Servlet 3.1 containers and also on other non-blocking runtimes such as Netty and Undertow.
Each runtime is adapted to a set of shared, reactive `ServerHttpRequest` and
`ServerHttpResponse` abstractions that expose the request and response body
as `Flux<DataBuffer>` with full backpressure support on the read and the
write side.
The `spring-core` module provides reactive `Encoder` and `Decoder` contracts
that enable the serialization of a `Flux` of bytes to and from typed objects
along with some basic implementations.
The `spring-web` modules adds JSON and XML implementations for use in reactive
web applications and also provides support for SSE streaming and zero-copy
file transfer.
The `spring-web-reactive` module defines many of the same contracts as
Spring MVC such as `HandlerMapping` and `HandlerAdapter` among others.
These reactive counterparts have asynchronous and non-blocking semantics and
operate on the reactive HTTP request and response abstractions.
The end result is a programming model identical to today's Spring MVC but
supporting reactive types and executing on a reactive, non-blocking foundation.
For example a controller method can declare any of the following as a method argument:
* `@RequestBody Account account` -- the account is deserialized without
blocking before the controller method is invoked.
* `@RequestBody Mono<Account> account` -- the controller can use the `Mono`
type to declare the logic execute when the account is deserialized.
* `@RequestBody Single<Account> account` -- same but with RxJava
* `@RequestBody Flux<Account>` accounts` -- streaming scenario.
* `@RequestBody Observable<Account> accounts` -- streaming with RxJava.
The same principle also applies on the side of return value handling.
[[web-reactive-client]]
=== Reactive Web Client
Spring Framework 5 adds a new reactive `WebClient` in addition to the existing `RestTemplate`.
Much like on the server side each supported HTTP client is adapted to a set of shared,
reactive `ClientHttpRequest` and `ClientHttpResponse` abstractions that expose the request
and response body as `Flux<DataBuffer>` with full backpressure support on the read and
the write side. The `Encoder` and `Decoder` abstractions from `spring-core` also used on
the client side for serialization of a `Flux` of bytes to and from typed objects.
Below is an example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
ClientHttpConnector httpConnector = new ReactorClientHttpConnector();
WebClient webClient = new WebClient(httpConnector);
Mono<Account> response = webClient
.perform(get("http://example.com/accounts/1").accept(APPLICATION_JSON))
.extract(body(Account.class));
----
The above example assumes the import of static methods from `ClientWebRequestBuilder`
and `ResponseExtractors`. The enable a fluent syntax similar to that of the MockMvc API
from Spring MVC Test. The same can also be done with RxJava. Simply replace with static
imports from `RxJava1ClientWebRequestBuilder` and `RxJava1ResponseExtractors`:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
Single<Account> response = webClient
.perform(get("http://example.com/accounts/1").accept(APPLICATION_JSON))
.extract(body(Account.class));
----
[[web-reactive-getting-started]]
== Getting Started
[[web-reactive-getting-started-boot]]
=== Spring Boot Starter
The quickest way to get started is through the experimental Spring Boot Web Reactive
starter available on http://start.spring.io. It does all the work so you can simply start
writing `@Controller` classes. By default the starter runs with Tomcat but you can change
the dependencies and use one of the other supported HTTP runtimes.
[[web-reactive-getting-started-manual]]
=== Manual Bootstrapping
It is also easy to get started by writing a few lines of code:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
AnnotationConfigApplicationContext context;
context = new AnnotationConfigApplicationContext();
context.register(WebReactiveConfiguration.class); // (1)
context.refresh();
DispatcherHandler handler = new DispatcherHandler(); // (2)
handler.setApplicationContext(context);
HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(handler).build();
HttpServer server = new TomcatHttpServer(); // (3)
server.setPort(8080);
server.setHandler(httpHandler);
server.afterPropertiesSet();
server.start();
----
The `WebReactiveConfiguration` at (1) is the Web Reactive Java config from the `spring-web-reactive`
and is similar in purpose to the MVC Java config from `spring-webmvc`. It provides the
the web framework configuration required to get started leaving you only to
declare your own `@Controller' beans.
The `DispatcherHandler` at (2) is the equivalent of the `DispatcherServlet` in Spring MVC.
The `HttpServer` at (3) is an abstraction from the
https://github.com/spring-projects/spring-framework/tree/master/spring-web/src/test/java/org/springframework/http/server/reactive/bootstrap[test sources]
of the `spring-web-reactive` module that's used for the framework's own integration tests.
It comes with basic implementations of all supported runtimes.
[[web-reactive-getting-started-M1]]
=== Extent of M1 Support
For M1 the Spring Web Reactive module focuses on support for REST scenarios both
client and server-side. Basic HTML rendering with Freemarker is also supported but
limited to rendering, i.e. there is no support form submissions yet.
On the client side for M1 the Reactor Netty HTTP client is supported.

View File

@ -29,3 +29,5 @@ include::web-cors.adoc[leveloffset=+1]
include::web-integration.adoc[leveloffset=+1]
include::web-websocket.adoc[leveloffset=+1]
include::web-reactive.adoc[leveloffset=+1]