11[[webflux-fn]]
2- = Functional Programming Model
2+ = Functional Endpoints
3+
4+ Spring WebFlux provides a lightweight, functional programming model where functions
5+ are used to route and handle requests and where contracts are designed for immutability.
6+ It is an alternative to the annotated-based programming model but runs on the same
7+ <<web-reactive.adoc#webflux-reactive-spring-web>> foundation
8+
39
410[[webflux-fn-handler-functions]]
5- == HandlerFunctions
11+ == HandlerFunction
612
713Incoming HTTP requests are handled by a **`HandlerFunction`**, which is essentially a function that
814takes a `ServerRequest` and returns a `Mono<ServerResponse>`. The annotation counterpart to a
9- handler function would be a method with `@RequestMapping`.
15+ handler function is an `@RequestMapping` method .
1016
1117`ServerRequest` and `ServerResponse` are immutable interfaces that offer JDK-8 friendly access
12- to the underlying HTTP messages. Both are fully reactive by
13- building on top of Reactor: the request expose the body as `Flux` or `Mono`; the response accepts
14- any http://www.reactive-streams.org[Reactive Streams] `Publisher` as body.
18+ to the underlying HTTP messages with http://www.reactive-streams.org[Reactive Streams]
19+ non-blocking back pressure. The request exposes the body as Reactor `Flux` or `Mono`
20+ types; the response accepts any Reactive Streams `Publisher` as body (see
21+ <<web-reactive.adoc#webflux-reactive-libraries,Reactive Libraries>>).
22+
1523
1624`ServerRequest` gives access to various HTTP request elements:
1725the method, URI, query parameters, and -- through the separate `ServerRequest.Headers` interface
@@ -26,7 +34,7 @@ contains JSON, or JAXB if XML).
2634
2735 Flux<Person> people = request.bodyToFlux(Person.class);
2836
29- The two methods above ( `bodyToMono` and `bodyToFlux`) are, in fact, convenience methods that use the
37+ The above -- `bodyToMono` and `bodyToFlux`, are, in fact, convenience methods that use the
3038generic `ServerRequest.body(BodyExtractor)` method. `BodyExtractor` is
3139a functional strategy interface that allows you to write your own extraction logic, but common
3240`BodyExtractor` instances can be found in the `BodyExtractors` utility class. So, the above
@@ -43,7 +51,8 @@ a JSON content-type, and a body:
4351 Mono<Person> person = ...
4452 ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(person);
4553
46- And here is how to build a response with a 201 Created status, Location header, and empty body:
54+ And here is how to build a response with a 201 CREATED status, a `"Location"` header, and
55+ empty body:
4756
4857 URI location = ...
4958 ServerResponse.created(location).build();
@@ -111,7 +120,7 @@ variable `id`. We retrieve that `Person` via the repository, and create a JSON r
111120found. If it is not found, we use `switchIfEmpty(Mono<T>)` to return a 404 Not Found response.
112121
113122[[webflux-fn-router-functions]]
114- == RouterFunctions
123+ == RouterFunction
115124
116125Incoming requests are routed to handler functions with a **`RouterFunction`**, which is a function
117126that takes a `ServerRequest`, and returns a `Mono<HandlerFunction>`. If a request matches a
@@ -172,43 +181,23 @@ Most of the predicates found in `RequestPredicates` are compositions.
172181For instance, `RequestPredicates.GET(String)` is a composition of
173182`RequestPredicates.method(HttpMethod)` and `RequestPredicates.path(String)`.
174183
175- [[webflux-fn-running]]
176- === Running a Server
177-
178- Now there is just one piece of the puzzle missing: running a router function in an HTTP server.
179- You can convert a router function into a `HttpHandler` by using
180- `RouterFunctions.toHttpHandler(RouterFunction)`.
181- The `HttpHandler` allows you to run on a wide variety of reactive runtimes: Reactor Netty,
182- Servlet 3.1+, and Undertow.
183- Here is how we run a router function in Reactor Netty, for instance:
184184
185- [source,java,indent=0]
186- [subs="verbatim,quotes"]
187- ----
188- RouterFunction<ServerResponse> route = ...
189- HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
190- ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
191- HttpServer server = HttpServer.create(HOST, PORT);
192- server.newHandler(adapter).block();
193- ----
185+ [[webflux-fn-running]]
186+ == Running a server
194187
195- For Tomcat it looks like this:
188+ How do you run a router function in an HTTP server? A simple option is to convert a
189+ router function to an `HttpHandler` via `RouterFunctions.toHttpHandler(RouterFunction)`.
190+ The `HttpHandler` can then be used with a number of servers adapters.
191+ See <<web-reactive.adoc#webflux-httphandler,HttpHandler>> for server-specific
192+ instructions.
196193
197- [source,java,indent=0]
198- [subs="verbatim,quotes"]
199- ----
200- RouterFunction<ServerResponse> route = ...
201- HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
202- HttpServlet servlet = new ServletHttpHandlerAdapter(httpHandler);
203- Tomcat server = new Tomcat();
204- Context rootContext = server.addContext("", System.getProperty("java.io.tmpdir"));
205- Tomcat.addServlet(rootContext, "servlet", servlet);
206- rootContext.addServletMapping("/", "servlet");
207- tomcatServer.start();
208- ----
194+ it is also possible to run with a
195+ <<web-reactive.adoc#webflux-dispatcher-handler,DispatcherHandler>> setup -- side by side
196+ with annotated controllers. The easiest way to do that is through the
197+ <<web-reactive.adoc#webflux-config>> which creates the necessary configuration to
198+ handle requests with router and handler functions.
209199
210200
211- // TODO: DispatcherHandler
212201
213202[[webflux-fn-handler-filter-function]]
214203== HandlerFilterFunction
0 commit comments