<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> </dependencies>
El siguiente paso es construir una primera versión del servicio REST de Hola Mundo en este caso utilizando la anotación @RequestMapping.
package com.arquitecturajava.router;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HolaRESTService {
@RequestMapping("/hola")
public String hola() {
return "hola desde spring";
}
}
Si ejecutamos el proyecto de Spring boot

Nos mostrará los datos sin ningún problema.
Spring 4.3 GetMapping ,PostMapping etc
A partir de la versión 4.3 de Spring Framework existe la posibilidad de tener unas anotaciones algo más compactas y más sencillas de leer que se encarguen cada una de ellas de uno de los verbos HTTP (get,post, put,delete) . Veamos la modificación que es necesario aplicar.
package com.arquitecturajava.router;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HolaRESTService2 {
@GetMapping("/hola2")
public String hola() {
return "hola desde spring con getmapping";
}
}
El resultado es prácticamente el mismo solo que la anotación nos ayuda a simplificar y facilitar la lectura.

Spring WebFlux Router
A partir de Spring 5 tenemos la opción de usar Spring WebFlux Router que nos permite mapear el servicio sin añadir anotaciones al propio contenido de nuestra clase. Algo que permite centralizar y clarificar las configuraciones dejando las clases más limpias. Para que todo nos funcione correctamente deberemos actualizar el proyecto pom.xml para usar programación reactiva.
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> </dependencies>
Una vez realizada esta operación el siguiente paso es construir un servicio Reactivo con Monos o Fluxs.
package com.arquitecturajava.router;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
@Service
public class HolaRESTService3 {
public Mono<String> hola() {
return Mono.just("hola desde spring y configuracion funcional");
}
}
El último paso es cambiar el fichero de configuración de Spring para que acepte una nueva ruta.
package com.arquitecturajava.router;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.ServerResponse.ok;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
@SpringBootApplication
public class RouterApplication {
public static void main(String[] args) {
SpringApplication.run(RouterApplication.class, args);
}
@Bean
RouterFunction<ServerResponse> holaRoute(HolaRESTService3 holaService) {
return RouterFunctions.route(GET("/hola3"),req->ok().body(holaService.hola(),String.class));
}
}
Como podemos observar la ruta en este caso se denomina /hola3 y esta disponible a traves de un mapeo que se hace con programación funcional . El servicio no incluye ningún RequestMapping ni RestResource.

Si ejecutamos el programa el nuevo servicio queda publicado:

Conclusiones
Las nuevas capacidades de programación Reactiva de Spring 5 nos aportan nuevos enfoques en la programación y la programación funcional suma a la hora de abordar configuraciones compleja.
Al usar webflux, qué ventaja ves de usar routing basado en funciones vs el @RestController de siempre que es igualmente soportado en su forma reactiva?
Una configuración más flexible a través del uso de programación funcional
Pero a mi modo de ver , añade complejidad al uso. Si comparamos los 2 sistemas, se puede ver fácilmente que el primer ejemplo, es mucho más entendible.
En el segundo, ya tenemos que empezar a sumar más complejidad, más clases, devuelve un tipo Mono,
pero que construye llamando a .just() ?? y tenemos que parsear con un String.class. ??
Supongo que las tendrá alguna ventaja , porque si es por claridad , personalmente, se pierde la sencillez inicial.
Es una buena opinión Rafa . Es evidente que las anotaciones son más claras y esta todo más integrado. Pero el enfoque funcional permitirá a futuro centralizar y sobre todo poder abordar situaciones de mayor complejidad a nivel configurativo
Muchas gracias
de nada 🙂