Spring WebFlux - Programación reactiva Spring
Spring WebFlux es el nuevo módulo introducido en Spring 5. Spring WebFlux es el primer paso hacia el modelo de programación reactiva en Spring Framework.
Programación reactiva de primavera
Si es nuevo en el modelo de programación reactiva, le sugiero que lea los siguientes artículos para aprender sobre la programación reactiva.
- Manifiesto Reactivo
- Transmisiones reactivas
- Flujos reactivos de Java 9
- RxJava
Si es nuevo en Spring 5, consulte las características de Spring 5.
Primavera WebFlux
- Mono: implementa Publisher y devuelve 0 o 1 elementos
- Flux: implementa Publisher y devuelve N elementos.
Spring WebFlux Hola Mundo Ejemplo
Spring WebFlux Maven Dependencias
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.journaldev.spring</groupId>
<artifactId>SpringWebflux</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Spring WebFlux</name>
<description>Spring WebFlux Example</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<jdk.version>1.9</jdk.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<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>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Las dependencias más importantes son spring-boot-starter-webflux
y spring-boot-starter-parent
. Algunas otras dependencias son para crear casos de prueba JUnit.
Manejador Spring WebFlux
El método Spring WebFlux Handler maneja la solicitud y devuelve Mono
o Flux
como respuesta.
package com.journaldev.spring.component;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
@Component
public class HelloWorldHandler {
public Mono<ServerResponse> helloWorld(ServerRequest request) {
return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN)
.body(BodyInserters.fromObject("Hello World!"));
}
}
Observe que el componente reactivo Mono
contiene el cuerpo ServerResponse
. También mire la cadena de funciones para establecer el tipo de contenido devuelto, el código de respuesta y el cuerpo.
Enrutador Spring WebFlux
El método de enrutador se utiliza para definir rutas para la aplicación. Estos métodos devuelven el objeto RouterFunction
que también contiene el cuerpo ServerResponse
.
package com.journaldev.spring.component;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
@Configuration
public class HelloWorldRouter {
@Bean
public RouterFunction<ServerResponse> routeHelloWorld(HelloWorldHandler helloWorldHandler) {
return RouterFunctions.route(RequestPredicates.GET("/helloWorld")
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), helloWorldHandler::helloWorld);
}
}
Entonces, estamos exponiendo un método GET para /helloWorld
y la llamada del cliente debe aceptar una respuesta de texto sin formato.
Aplicación de arranque de primavera
Configuremos nuestra sencilla aplicación WebFlux con Spring Boot.
package com.journaldev.spring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Si observa el código anterior, no hay nada relacionado con Spring WebFlux. Pero Spring Boot configurará nuestra aplicación como Spring WebFlux ya que hemos agregado la dependencia del módulo spring-boot-starter-webflux
.
Compatibilidad con módulos de Java 9
Nuestra aplicación está lista para ejecutarse en Java 8, pero si está utilizando Java 9, también debemos agregar la clase module-info.java
.
module com.journaldev.spring {
requires reactor.core;
requires spring.web;
requires spring.beans;
requires spring.context;
requires spring.webflux;
requires spring.boot;
requires spring.boot.autoconfigure;
exports com.journaldev.spring;
}
Ejecución de la aplicación Spring WebFlux Spring Boot
2018-05-07 15:01:47.893 INFO 25158 --- [ main] o.s.w.r.f.s.s.RouterFunctionMapping : Mapped ((GET && /helloWorld) && Accept: [text/plain]) -> com.journaldev.spring.component.HelloWorldRouter$$Lambda$501/704766954@6eeb5d56
2018-05-07 15:01:48.495 INFO 25158 --- [ctor-http-nio-1] r.ipc.netty.tcp.BlockingNettyContext : Started HttpServer on /0:0:0:0:0:0:0:0:8080
2018-05-07 15:01:48.495 INFO 25158 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2018-05-07 15:01:48.501 INFO 25158 --- [ main] com.journaldev.spring.Application : Started Application in 1.86 seconds (JVM running for 5.542)
Está claro a partir de los registros que nuestra aplicación se ejecuta en el servidor Netty en el puerto 8080. Sigamos adelante y probemos nuestra aplicación.
Prueba de la aplicación Spring WebFlux
Podemos probar nuestra aplicación con varios métodos.
Resumen
En esta publicación, aprendimos sobre Spring WebFlux y cómo crear un servicio web Restful reactivo hello world. Es bueno ver que los marcos populares como Spring están apoyando el modelo de programación reactiva. Pero tenemos mucho que cubrir porque si todas sus dependencias no son reactivas y sin bloqueo, entonces su aplicación tampoco es verdaderamente reactiva. Por ejemplo, los proveedores de bases de datos relacionales no tienen controladores reactivos porque dependen de JDBC, que no es reactivo. Por lo tanto, la API de Hibernate tampoco es reactiva. Entonces, si está utilizando bases de datos relacionales, todavía no puede crear una aplicación verdaderamente reactiva. Tengo la esperanza de que va a cambiar más temprano que tarde.
Puede descargar el código del proyecto desde mi repositorio de GitHub.
Referencia: Documentación Oficial