Backend Development 7 min read

Mastering Spring Boot RouterFunction: Build Clean Reactive Routes

This guide explains how to use Spring Boot's RouterFunction API to create, combine, and nest reactive routes with RequestPredicates, demonstrating practical code examples for GET, POST, and complex route compositions in a Spring WebFlux application.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Spring Boot RouterFunction: Build Clean Reactive Routes

Overview

Router functions map incoming requests to a HandlerFunction . Instead of writing them manually, you typically use the static methods in the RouterFunctions class. RouterFunctions.route() provides a fluent builder, while RouterFunctions.route(RequestPredicate, HandlerFunction) offers a direct creation method.

The builder style route() is recommended because it supplies convenient shortcuts for common mappings, such as GET(String, HandlerFunction) and POST(String, HandlerFunction) .

Predicates

You can implement custom RequestPredicate s, but the RequestPredicates class already supplies common implementations based on path, HTTP method, content type, etc.

<code>RouterFunction&lt;ServerResponse&gt; route = RouterFunctions.route()
    .GET("/hello-world", accept(MediaType.TEXT_PLAIN),
        request -> ServerResponse.ok().bodyValue("Hello World"))
    .build();</code>

Predicates can be combined using RequestPredicate.and(other) (both must match) or RequestPredicate.or(other) (either may match). Many predicates are composites; for example, RequestPredicates.GET(String) combines method(HttpMethod) and path(String) .

Routes

Router functions are evaluated sequentially: if the first route does not match, the next is tried. Therefore, more specific routes should be declared before generic ones, especially when registering the router as a Spring bean.

Multiple router functions can be merged using:

add(RouterFunction) on the builder

RouterFunction.and(RouterFunction)

RouterFunction.andRoute(RequestPredicate, HandlerFunction) (shortcut for nested routes)

<code>import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.web.reactive.function.server.RequestPredicates.*;

PersonRepository repository = ...;
PersonHandler handler = new PersonHandler(repository);
RouterFunction&lt;ServerResponse&gt; otherRoute = ...;

RouterFunction&lt;ServerResponse&gt; route = route()
    .GET("/person/{id}", accept(APPLICATION_JSON), handler::getPerson) // 1
    .GET("/person", accept(APPLICATION_JSON), handler::listPeople)   // 2
    .POST("/person", handler::createPerson)                        // 3
    .add(otherRoute)                                                // 4
    .build();</code>

GET /person/{id} with JSON Accept header routes to PersonHandler.getPerson .

GET /person with JSON Accept header routes to PersonHandler.listPeople .

POST /person routes to PersonHandler.createPerson .

otherRoute is an externally defined router function added to the composition.

Nested Routes

When several routes share a common predicate (e.g., a base path), you can group them using path() :

<code>RouterFunction&lt;ServerResponse&gt; route = route()
    .path("/person", builder -> builder
        .GET("/{id}", accept(APPLICATION_JSON), handler::getPerson)
        .GET(accept(APPLICATION_JSON), handler::listPeople)
        .POST(handler::createPerson))
    .build();</code>

Further nesting is possible with nest() to combine additional predicates such as an Accept header:

<code>RouterFunction&lt;ServerResponse&gt; route = route()
    .path("/person", b1 -> b1
        .nest(accept(APPLICATION_JSON), b2 -> b2
            .GET("/{id}", handler::getPerson)
            .GET(handler::listPeople))
        .POST(handler::createPerson))
    .build();</code>

Conclusion

The article covered the practical use of RouterFunction in Spring Boot, including basic route creation, predicate composition, route combination techniques, and nested routing for shared predicates.

Javabackend-developmentSpring BootWebFluxrouterfunction
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.