Como crear un CRUD con Spring Framework 5.2.13 y Bootstrap 4.6 – Parte 3
En esta página:
Demo
En la Parte anterior llamada Como crear un CRUD con Spring Framework 5.2.13 y Bootstrap 4.6 – Parte 2, configuramos la base de datos, creamos una tabla llamda postres en donde almacenaremos los registros, asimismo realizamos la conexión a la base de datos en Spring Framework mediante el archivo application.properties, en donde realizamos otras configuraciones para que el proyecto funcione correctamente y comenzamos creando el modelo del sistema CRUD, basandonos en una estructura MVC (Modelo, Vista y Controlador). En esta 3ra parte vamos a trabajar en el controlador para el sistema CRUD, vamos con ello.
Partes
Antes de continuar con este Post, te invito a leer los siguientes artículos:
- Que es Spring Framework y Otros Detalles
- 5 Consejos para escribir Controladores Spring MVC
- Como funciona la anotación @Value en Spring
- Cual es la diferencia entre Spring (Framework) y Spring Boot
- Como Crear Nuestra Primera Aplicación Básica con Spring Framework – Parte 1
- Puedes leer más en la categoría Spring
Asimismo, te invito a escuchar el Podcast: “Herramientas Online Para el Trabajo en Equipo” y “La Inteligencia Artificial (IA) y el Machine Learning (ML) Siempre Trabajan de la Mano” (Anchor Podcast):
Spotify: | Sound Cloud: | Apple Podcasts | Anchor Podcasts |
Bien ahora continuemos con el Post: Como crear un CRUD con Spring Framework 5.2.13 y Bootstrap 4.6 – Parte 3.
Controlador
Vamos a comenzar creando el controlador, para esto creo un directorio llamado Controller y dentro de el creo un archivo con el nombre Controlador.java en sistemacrud > src > main > java > com > sistemacrud > sistemacrud > Controller > Controlador.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/sistemacrud ├── /.mvn ├── /src ├── /main ├── /java ├── /com ├── /sistemacrud ├── /sistemacrud ├── /Controller // Creo este directorio ├── Controlador.java // Creo y Abro este Archivo ├── /Model ├── SistemacrudApplication.java ├── /target ├── .gitignore ├── HELP.md ├── mvnw ├── mvnw.cmd ├── porn.xml |
Abro el archivo Controlador.java y e importo algunas librerías y utilidades necesarias para mi controlador.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
package com.sistemacrud.sistemacrud.Controller; import java.util.List; import java.util.Optional; import com.sistemacrud.sistemacrud.InterfaceService.InterfacePostreService; import com.sistemacrud.sistemacrud.Model.Postre; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.util.StringUtils; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.springframework.web.bind.annotation.RequestMethod; |
Paso seguido creo una clase publica con el nombre Controladory dentro de ella empiezo llamando a mi IntefacePostreService la cual crearemos mas adelante y una variable UPLOADS con la ruta en donde se guardarán las imagenes de cada registro.
NOTA: He colocado comentarios para explicar que hace cada línea de código.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@Controller @RequestMapping public class Controlador { @Autowired private InterfacePostreService service; // Directorio a donde se subirán las imágenes public static String UPLOAD = "src/main/resources/static/uploads/"; // Acá va el resto del código } |
Vista Principal (Read)
Creo mi método listar() en donde cargaremos una vista con una tabla HTML que contendrá todos los registros desde la base de datos:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Vista Principal @GetMapping("/") public String listar(Model model) { // Seleccionamos el modelo 'Postres' y listamos los registros desde la Base de datos List < Postre > postres = service.listar(); model.addAttribute("postres", postres); return "index"; } |
Crear (Create)
Ahora creo un método llamado crear() que llamará a una vista con un formulario HTML para agregar un nuevo registro:
1 2 3 4 5 6 7 8 9 10 11 |
/ Crear Registro @GetMapping("/crear") public String crear(Model model) { // Cargamos el modelo 'Postre' y mostramos un formulario para crear un nuevo registro model.addAttribute("postres", new Postre()); return "crear"; } |
El método anterior sirve para mostrar un formulario para crear un registro, pero para el proceso de almacenamiento en la base de datos y la subida de la imágen al servidor voy a crear un método llamado guardar():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// Proceso para Guardar los datos en la Base de datos y subir la imágen al servidor @PostMapping("/guardar") public String guardar(@Validated Postre p, Model model, @RequestParam("img") MultipartFile multipartFile, RedirectAttributes redirAttrs) throws IOException { // Obtenemos el nombre la imagen String nombreImagen = StringUtils.cleanPath(multipartFile.getOriginalFilename()); System.out.println(nombreImagen); p.setImagen(nombreImagen); // Subimos la imagen al servidor byte[] bytes = multipartFile.getBytes(); Path path = Paths.get(UPLOADS + multipartFile.getOriginalFilename()); Files.write(path, bytes); // Guardamos los datos del formulario en la base de datos this.service.save(p); // Enviamos un mensaje a la vista principal redirAttrs.addFlashAttribute("success", "Creado Correctamente !"); // Luego de realizar las tareas correspondientes, redireccionamos a la vista principal return "redirect:/"; } |
Leer (Read)
Voy a crear el método leer() que servirá para leer un item de la base de datos de manera independiente haciendo uso de su id:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// Vista para Leer un Registro @GetMapping("/leer/{id}") @RequestMapping(value = "/leer/{id}", method = RequestMethod.GET) public String leer(@PathVariable("id") int id, Model model) { // Recibimos el 'id' del registro a leer Optional < Postre > postres = this.service.leer(id); if (postres.isEmpty()) { System.out.println("none"); } else { System.out.println(postres.get().getNombre()); } // Seleccionamos los datos de la tabla 'postres' model.addAttribute("postres", postres); // Cargamos la vista para leer un registro return "leer"; } |
Actualizar (Update)
Creo el método actualizar() para mostrar un formulario HTML para actualizar los datos de un registro:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Vista para Actualizar un Registro @GetMapping("/actualizar/{id}") @RequestMapping(value = "/actualizar/{id}", method = RequestMethod.GET) public String actualizar(@PathVariable("id") int id, Model model) { // Recibimos el 'id' del registro que se va Actualizar Optional < Postre > postres = this.service.getId(id); // Seleccionamos los datos de la tabla 'postres' model.addAttribute("postres", postres); // Luego de realizar las tareas correspondientes, redireccionamos a la vista principal return "actualizar"; } |
El método anterior sirve para mostrar un formulario para actualizar un registro, pero para el proceso de actualización en la base de datos y la subida de la imágen al servidor voy a crear un método llamado update():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
// Proceso Para Actualizar un Registro @PostMapping("/update/{id}") public String update(@Validated Postre p, @PathVariable("id") int id, Model model, @RequestParam("img") MultipartFile multipartFile, RedirectAttributes redirAttrs) throws IOException, ClassNotFoundException { // Obtenemos el nombre la imagen String nombreImagen = StringUtils.cleanPath(multipartFile.getOriginalFilename()); System.out.println(nombreImagen); // Verificamos si el usuario cargo una imagen en el formulario if (nombreImagen == null || nombreImagen.length() == 0) { // Si el usuario no cargo una imagen en el formulario // Realizo una Conexión a la base de datos para obtener la imagen actual del registro // Recibimos el 'id' del registro a leer Optional < Postre > postres = this.service.leer(id); if (postres.isEmpty()) { System.out.println("none"); } else { System.out.println(postres.get().getImagen()); // Mantenemos el mismo nombre de imagen actual p.setImagen(postres.get().getImagen()); } System.out.println("No se cargo una imagen"); } else { // Si el usuario si cargo una imagen en el formulario // Seleccionamos el nombre de la imagen, el cual se guardará en la columna 'img' p.setImagen(nombreImagen); // Subimos la imagen al servidor byte[] bytes = multipartFile.getBytes(); Path path = Paths.get(UPLOADS + multipartFile.getOriginalFilename()); Files.write(path, bytes); System.out.println("Si se cargo una imagen"); } // Guardamos los datos del formulario en la base de datos this.service.save(p); // Enviamos un mensaje a la vista principal redirAttrs.addFlashAttribute("success", "Actualizado Correctamente !"); // Luego de realizar las tareas correspondientes, redireccionamos a la vista principal return "redirect:/"; } |
Ahora pasemos al método para eliminar un registro de la base de datos.
Eliminar (Delete)
Por último vamos a necesitar un método para eliminar los registros, creo el método eliminar() para esta tarea:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// Eliminar un Registro @GetMapping("/eliminar/{id}") public String delete(@PathVariable int id, Model model, RedirectAttributes redirAttrs) { // Recibimos el 'id' del registro a eliminar this.service.delete(id); // Enviamos un mensaje a la vista principal redirAttrs.addFlashAttribute("success", "Eliminado Correctamente !"); // Luego de realizar las tareas correspondientes, redireccionamos a la vista principal return "redirect:/"; } |
A continuación el código completo del archivo Controlador.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
package com.sistemacrud.sistemacrud.Controller; import java.util.List; import java.util.Optional; import com.sistemacrud.sistemacrud.InterfaceService.InterfacePostreService; import com.sistemacrud.sistemacrud.Model.Postre; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import org.springframework.util.StringUtils; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping public class Controlador { @Autowired private InterfacePostreService service; //private static String UPLOAD_FOLDER = "F://old_h_xampp//htdocs//xampp//nc//tutoriales//blog//sistemacrud//src//main//resources//static//uploads//"; // Directorio a donde se subirán las imágenes public static String UPLOADS = "src/main/resources/static/uploads/"; // Listar Registros @GetMapping("/") public String listar(Model model){ // Seleccionamos el modelo 'Postres' y listamos los registros desde la Base de datos List<Postre> postres = service.listar(); model.addAttribute("postres", postres); return "index"; } // Vista Para Crear un Registro @GetMapping("/crear") public String crear(Model model){ // Cargamos el modelo 'Postre' y mostramos un formulario para crear un nuevo registro model.addAttribute("postres", new Postre()); return "crear"; } // Proceso para Guardar los datos en la Base de datos y subir la imágen al servidor @PostMapping("/guardar") public String guardar(@Validated Postre p, Model model, @RequestParam("img") MultipartFile multipartFile, RedirectAttributes redirAttrs) throws IOException { // Obtenemos el nombre la imagen String nombreImagen = StringUtils.cleanPath(multipartFile.getOriginalFilename()); System.out.println(nombreImagen); p.setImagen(nombreImagen); // Subimos la imagen al servidor byte[] bytes = multipartFile.getBytes(); Path path = Paths.get(UPLOADS + multipartFile.getOriginalFilename()); Files.write(path, bytes); // Guardamos los datos del formulario en la base de datos this.service.save(p); // Enviamos un mensaje a la vista principal redirAttrs.addFlashAttribute("success", "Creado Correctamente !"); // Luego de realizar las tareas correspondientes, redireccionamos a la vista principal return "redirect:/"; } // Vista para Leer un Registro @GetMapping("/leer/{id}") @RequestMapping(value="/leer/{id}", method = RequestMethod.GET) public String leer(@PathVariable("id") int id, Model model){ // Recibimos el 'id' del registro a leer Optional<Postre> postres = this.service.leer(id); if (postres.isEmpty()) { System.out.println("none"); } else { System.out.println(postres.get().getNombre()); } // Seleccionamos los datos de la tabla 'postres' model.addAttribute("postres", postres); // Cargamos la vista para leer un registro return "leer"; } // Vista para Actualizar un Registro @GetMapping("/actualizar/{id}") @RequestMapping(value="/actualizar/{id}", method = RequestMethod.GET) public String actualizar(@PathVariable("id") int id, Model model){ // Recibimos el 'id' del registro que se va Actualizar Optional<Postre> postres = this.service.getId(id); // Seleccionamos los datos de la tabla 'postres' model.addAttribute("postres", postres); // Luego de realizar las tareas correspondientes, redireccionamos a la vista principal return "actualizar"; } // Proceso Para Actualizar un Registro @PostMapping("/update/{id}") public String update(@Validated Postre p, @PathVariable("id") int id, Model model, @RequestParam("img") MultipartFile multipartFile, RedirectAttributes redirAttrs) throws IOException, ClassNotFoundException { // Obtenemos el nombre la imagen String nombreImagen = StringUtils.cleanPath(multipartFile.getOriginalFilename()); System.out.println(nombreImagen); // Verificamos si el usuario cargo una imagen en el formulario if(nombreImagen == null || nombreImagen.length() == 0) { // Si el usuario no cargo una imagen en el formulario // Realizo una Conexión a la base de datos para obtener la imagen actual del registro // Recibimos el 'id' del registro a leer Optional<Postre> postres = this.service.leer(id); if (postres.isEmpty()) { System.out.println("none"); } else { System.out.println(postres.get().getImagen()); // Mantenemos el mismo nombre de imagen actual p.setImagen(postres.get().getImagen()); } System.out.println("No se cargo una imagen"); } else { // Si el usuario si cargo una imagen en el formulario // Seleccionamos el nombre de la imagen, el cual se guardará en la columna 'img' p.setImagen(nombreImagen); // Subimos la imagen al servidor byte[] bytes = multipartFile.getBytes(); Path path = Paths.get(UPLOADS + multipartFile.getOriginalFilename()); Files.write(path, bytes); System.out.println("Si se cargo una imagen"); } // Guardamos los datos del formulario en la base de datos this.service.save(p); // Enviamos un mensaje a la vista principal redirAttrs.addFlashAttribute("success", "Actualizado Correctamente !"); // Luego de realizar las tareas correspondientes, redireccionamos a la vista principal return "redirect:/"; } // Eliminar un Registro @GetMapping("/eliminar/{id}") public String delete(@PathVariable int id, Model model, RedirectAttributes redirAttrs){ // Recibimos el 'id' del registro a eliminar this.service.delete(id); // Enviamos un mensaje a la vista principal redirAttrs.addFlashAttribute("success", "Eliminado Correctamente !"); // Luego de realizar las tareas correspondientes, redireccionamos a la vista principal return "redirect:/"; } } |
Con esto ya tenemos nuestro controlador con todos los métodos necesarios para que el sistema CRUD funcione sin problemas.
Interface de Servicio
En Java necesitamos crear un interface de servicio que integrará el modelo Postres con ciertos métodos indispensable para el sistema CRUD. Entonces creo un directorio llamado InterfaceService y dentro de el creo el archivo InterfacePostreService.java en sistemacrud > src > main > java > com > sistemacrud > sistemacrud > InterfaceService > InterfacePostreService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/sistemacrud ├── /.mvn ├── /src ├── /main ├── /java ├── /com ├── /sistemacrud ├── /sistemacrud ├── /Controller ├── /InterfaceService // Creo este directorio ├── InterfacePostreService.java // Creo y Abro este Archivo ├── /Model ├── SistemacrudApplication.java ├── /target ├── .gitignore ├── HELP.md ├── mvnw ├── mvnw.cmd ├── porn.xml |
Abro el archivo InterfacePostreService.java y dentro de el agrego lo siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.sistemacrud.crudspringboot.InterfaceService; import java.util.List; import java.util.Optional; import com.sistemacrud.crudspringboot.Model.Postre; public interface InterfacePostreService { // Métodos public List<Postre> listar(); public Optional<Postre> getId(int id); public int save(Postre p); public void delete(int id); } |
Bien, hasta aquí llegamos con esta 3ra parte del tutorial en donde hemos creado nuestro controlador con sus métodos necesarios para realizar las operaciones CRUD (Create, Read, Delete y Update). Asimismo definimos una interface de servicio con ciertos métodos indispensables.
Ten Paciencia, lo que quiero es que conozcas bien como se crea este proyecto y no llenarte el capitulo de mucho contenido porque te puedes marear y no tendrás un óptimo aprendizaje.
Nota (s)
- En la siguiente parte vamos a configurar un repositorio y un servicio para nuestro proyecto.
- Los pasos mencionados en este tutorial pueden cambiar en un futuro, esto no depende de mi, si no de la organización que da soporte a Spring Framework, que suele cambiar el orden y las opciones de su herramienta.
- No olvides que debemos usar la Tecnología para hacer cosas Buenas por el Mundo.
Síguenos en nuestras Redes Sociales para que no te pierdas nuestros próximos contenidos.
- Spring Tutoriales
- 19-05-2022
- 10-08-2023
- Crear un Post - Eventos Devs - Foro
Social
Redes Sociales (Developers)
Redes Sociales (Digital)