Acabamos de ver como usar Java equals y hashcode
El concepto de Spring 5 Reactive es un concepto relativamente nuevo y para el cual necesitamos tener instalado Spring 5 y WebFlux para poder hacer uso de él. La programación Reactiva se apoya fundamentalmente en el concepto de Reactive Streams flujos de trabajo fuertemente asíncronos que permiten una flexibilidad alta a la hora de trabajar con ellos. Vamos a construir unos ejemplos fundamentales con Spring 5 y ThymeLeaf para entender mejor como funciona este tipo de programación asíncrona. El primer paso es ir a Spring initializer y descargarnos un proyecto que incluya las siguientes dependencias:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>
Una vez que tenemos las dependencias instaladas el siguiente paso es crearnos con Spring 5 un Repositorio que nos devuelva información . En este caso voy a apostar por un repositorio sencillo en memoria que contenga una lista de productos.
package com.arquitecturajava.spring5.reactiva;
public class Producto {
private int numero;
private String concepto;
private int importe;
public int getNumero() {
return numero;
}
public void setNumero(int numero) {
this.numero = numero;
}
public String getConcepto() {
return concepto;
}
public void setConcepto(String concepto) {
this.concepto = concepto;
}
public int getImporte() {
return importe;
}
public void setImporte(int importe) {
this.importe = importe;
}
public Producto(int numero, String concepto, int importe) {
super();
this.numero = numero;
this.concepto = concepto;
this.importe = importe;
}
public Producto() {
super();
}
} Construida la clase Producto , el siguiente paso es construir la clase Repositorio con una lista de elementos estáticos en memoria.
package com.arquitecturajava.spring5.reactiva;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
@Repository
public class ProductoRepository {
private static List<Producto> lista= new ArrayList<>();
static {
lista.add(new Producto(1,"ordenador",200));
lista.add(new Producto(2,"tablet",300));
lista.add(new Producto(3,"auricular",200));
}
public Flux<Producto> buscarTodos() {
return Flux.fromIterable(lista).delayElements(Duration.ofSeconds(3));
}
} Spring 5 Reactive y Flux
Como se puede observar tenemos un método un poco especial buscarTodos() que devuelve un Flux . Un Flux no es ni mas ni menos que una colección de elementos asíncronos que nos van llegando cada x tiempo. En este caso ese tiempo es 3 segundos. Es decir cada item nos llega después de que han pasado 3 segundos.
Es momento de definir un Controlador que trabaje con este flujo de elementos asíncronos:
package com.arquitecturajava.spring5.reactiva;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.thymeleaf.spring5.context.webflux.IReactiveDataDriverContextVariable;
import org.thymeleaf.spring5.context.webflux.ReactiveDataDriverContextVariable;
@Controller
public class ControladorReactivo {
@Autowired
private ProductoRepository repositorio;
@RequestMapping("/lista")
public String lista(Model modelo) {
//variable reactiva
IReactiveDataDriverContextVariable listaReactiva =
new ReactiveDataDriverContextVariable(repositorio.buscarTodos(), 1);
modelo.addAttribute("listaProductos", listaReactiva);
return "lista";
}
}
Acabamos de construir un Controlador con Spring 5 Reactive este controlador solo dispone de una URL de acceso que es /lista . Esta URL es evidentemente una vista de Thymeleaf que recibe como parte de su modelo en vez de un objeto o una lista clasica , recibe un ReactiveDataDriverContextVariable . Es decir una variable Reactiva que tendrá que presentar en el interface de usuario
Thymeleaf y Vistas
Vamos a ver el contenido de la vista que se trata de un html relativamente sencillo:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<table>
<tr th:each="producto:${listaProductos}">
<td th:text="${producto.numero}"></td>
<td th:text="${producto.concepto}"></td>
<td th:text="${producto.importe}"></td>
</tr>
</table>
</body>
</html> Si ahora ejecutamos la aplicación nos daremos cuenta que la información nos va llegando poco a poco . Al pasar los primeros 3 segundos nos llegará el primer item:
Pasados 3 segundos nos llegara el segundo elemento y pasados otros 3 el último:
Acabamos de diseñar un ejemplo de Spring 5 Reactive con ThymeLeaf