Enviar datos por formulario y procesarlos usando Spring Boot
En este post te voy a enseñar a obtener datos de formulario en Spring Boot usando el motor de plantillas Thymeleaf para mostrar el formulario.
Vamos a ver un ejemplo de un formulario, desde dibujarlo hasta procesarlo en el controlador, usando una clase.
La entidad
Para trabajar con formularios en Spring Boot debemos definir una clase que opcionalmente puede ser una entidad. En este caso vamos a poner un ejemplo para un Producto.
Comenzamos definiendo la clase:
package hello;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Producto {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String nombre, codigo;
private Float precio, existencia;
public String getCodigo() {
return codigo;
}
public void setCodigo(String codigo) {
this.codigo = codigo;
}
public Float getPrecio() {
return precio;
}
public void setPrecio(Float precio) {
this.precio = precio;
}
public Float getExistencia() {
return existencia;
}
public void setExistencia(Float existencia) {
this.existencia = existencia;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
Es una simple clase que a su vez es entidad. Tiene getters, setters y propiedades.
Como lo dije hace un momento: no es obligatorio que la clase sea una entidad.
La ruta del formulario
Para mostrar el formulario debemos definir una ruta en donde se va a dibujar el mismo. Al dibujar la vista debemos pasar un objeto vacío de nuestra clase.
Entonces dentro de nuestro controlador definimos la ruta:
@GetMapping(value = "/agregar")
public String agregarProducto(Model model) {
model.addAttribute("producto", new Producto());
return "productos/agregar_producto";
}
Cuando se visite /agregar
se mostrará la vista llamada agregar_producto
dentro del directorio productos
, la cual veremos más adelante.
Por ahora fíjate en que estamos inyectando un modelo en la línea 2, y en la línea 3 estamos agregando el atributo llamado producto
con una instancia de la clase Producto
, que por defecto no tiene datos.
La vista del formulario
El formulario que vamos a procesar con Spring Boot es el siguiente:
Ahora en nuestra vista definimos un formulario, y a cada campo le asignamos una propiedad de nuestro objeto usando th:field
.
Además, definimos el atributo th:object
para indicar al formulario cuál objeto estamos llenando.
<form th:object="${producto}" th:action="@{/productos/agregar}" method="post">
<div class="form-group">
<label for="nombre">Nombre del producto</label>
<input th:field="*{nombre}" id="nombre" placeholder="Escribe el nombre del producto" type="text"
class="form-control">
</div>
<div class="form-group">
<label for="codigo">Código de barras</label>
<input th:field="*{codigo}" id="codigo" placeholder="Escribe el código del producto" type="text"
class="form-control">
</div>
<div class="form-group">
<label for="existencia">Existencia actual</label>
<input th:field="*{existencia}" id="existencia" placeholder="Cantidad actual del producto" type="number"
class="form-control">
</div>
<div class="form-group">
<label for="existencia">Precio</label>
<input th:field="*{precio}" id="precio" placeholder="Precio del producto" type="number"
class="form-control">
</div>
<button class="btn btn-success" type="submit">Guardar</button>
<a class="btn btn-warning" th:href="@{/productos/mostrar}">Ver todos</a>
</form>
Cada input
está relacionado con una propiedad del objeto. También es muy importante ver el th:action
del formulario, el cual irá a productos/agregar
pero con el método POST
.
Procesar formulario en controlador de Spring Boot
De nuevo en nuestro controlador vamos a definir otra ruta en donde se va a procesar el formulario enviado en Spring Boot.
La ruta queda así:
@PostMapping(value = "/agregar")
public String guardarProducto(@ModelAttribute Producto producto) {
// Aquí tienes a producto, el cual es un objeto con los campos llenados en el formulario
// Podrías guardarlo en la BD usando, por ejemplo (si tienes un repositorio):
// productosRepository.save(producto);
/* Más magia aquí */
}
Definimos nuestra ruta e inyectamos nuestra clase usando la anotación @ModelAttribute
, ahora tenemos todos los campos llenos a través de la variable producto, con ella se puede hacer cualquier cosa que se haría con el objeto normal.
Código completo del controlador
Si quieres ver las anotaciones y el código del controlador (para guiarte y saber cuáles cosas importar) aquí lo dejo:
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
@RequestMapping(path = "/productos")
public class ProductosController {
@Autowired
private ProductosRepository productosRepository;
@GetMapping(value = "/agregar")
public String agregarProducto(Model model) {
model.addAttribute("producto", new Producto());
return "productos/agregar_producto";
}
@GetMapping(value = "/mostrar")
public String mostrarProductos(Model model) {
model.addAttribute("productos", productosRepository.findAll());
return "productos/ver_productos";
}
@PostMapping(value = "/eliminar")
public String eliminarProducto(@ModelAttribute Producto producto, RedirectAttributes redirectAttrs) {
redirectAttrs
.addFlashAttribute("mensaje", "Eliminado correctamente")
.addFlashAttribute("clase", "warning");
productosRepository.deleteById(producto.getId());
return "redirect:/productos/mostrar";
}
@PostMapping(value = "/editar")
public String actualizarProducto(@ModelAttribute Producto producto, RedirectAttributes redirectAttrs) {
productosRepository.save(producto);
redirectAttrs
.addFlashAttribute("mensaje", "Editado correctamente")
.addFlashAttribute("clase", "success");
return "redirect:/productos/mostrar";
}
@GetMapping(value = "/editar/{id}")
public String mostrarFormularioEditar(@PathVariable int id, Model model) {
model.addAttribute("producto", productosRepository.findById(id));
return "productos/editar_producto";
}
@PostMapping(value = "/agregar")
public String guardarProducto(@ModelAttribute Producto producto, RedirectAttributes redirectAttrs) {
productosRepository.save(producto);
redirectAttrs
.addFlashAttribute("mensaje", "Agregado correctamente")
.addFlashAttribute("clase", "success");
return "redirect:/productos/mostrar";
}
}
Recuerda que es una referencia, ya que en mi caso utilizo un repositorio, cosa que no tiene que ver con esto ya que aquí solo vimos cómo procesar un formulario con Spring Boot.
Para implementar este ejemplo, lo único que tienes hacer es crear tu propia clase y definir tus formularios.