Modulo-1-Introduccion-a-los-controladores-en-Spring-Boot (Autoguardado)
Modulo-1-Introduccion-a-los-controladores-en-Spring-Boot (Autoguardado)
controladores en Spring
Boot
by Pablo Guevara
En este módulo introductorio, se explora en detalle el concepto de controladores en Spring Boot y
su función en una aplicación web. Los controladores son componentes clave en la arquitectura
MVC (Modelo-Vista-Controlador) de Spring Boot y se utilizan para manejar las solicitudes HTTP
entrantes y enviar las respuestas correspondientes. Los controladores son responsables de recibir
los datos de entrada, invocar la lógica de negocio adecuada y devolver los resultados al cliente.
@GetMapping("/hello")
public String sayHello() {
return "¡Hola desde el controlador!";
}
@PostMapping("/data")
public User PostRequest() {
User user = new User();
user.setName("John Doe");
user.setEmail("[email protected]");
return user;
}
Módulo 2: Mapeo de rutas y parámetros en los
controladores
En este módulo, se explora cómo mapear rutas y manejar parámetros en los controladores de Spring Boot.
En el contexto de Spring Boot, el mapeo de rutas y parámetros en los controladores se refiere a la capacidad de definir cómo las
diferentes URL y los parámetros de solicitud se asignan a los métodos en los controladores de la aplicación. Esto permite que el
controlador responda a las solicitudes HTTP entrantes de manera adecuada y proporcione la respuesta correspondiente
En Spring Boot, los controladores son componentes que manejan las solicitudes web y definen la lógica de negocio asociada.
Para mapear rutas y parámetros, puedes utilizar las anotaciones proporcionadas por Spring MVC, como @RequestMapping,
@GetMapping, @PostMapping, etc.
A través de estas anotaciones, puedes definir la ruta de acceso a un método en el controlador y especificar el método HTTP al que
debe responder. Por ejemplo, puedes utilizar @GetMapping("/ruta") para asignar una ruta y el método HTTP GET a un método en
particular en el controlador.
Además, puedes manejar parámetros de solicitud en los controladores de Spring Boot. Hay diferentes tipos de parámetros que
puedes utilizar, como parámetros de ruta, parámetros de consulta y parámetros de cuerpo de solicitud. Estos parámetros te permiten
acceder y utilizar los datos proporcionados por el cliente en la solicitud.
Módulo 1: Introducción a los
tipos de peticiones HTTP
Stateless: El protocolo HTTP es stateless, lo que significa que cada solicitud se procesa de forma independiente, sin que el
servidor mantenga información sobre solicitudes anteriores del mismo cliente. Cada solicitud contiene toda la información
necesaria para que el servidor comprenda y responda apropiadamente.
Basado en texto: Las peticiones HTTP se basan en texto legible por humanos. Consisten en una línea de solicitud, encabezados
(headers) y, en algunos casos, un cuerpo (body) que puede contener datos adicionales.
Métodos de solicitud: Las peticiones HTTP utilizan diferentes métodos de solicitud para indicar la acción que se debe realizar en
el servidor. Los métodos más comunes son GET, POST, PUT y DELETE, que se describen a continuación.
Método HTTP
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
// Lógica para obtener un usuario por su ID
User user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
}
En Spring Boot, el manejo de códigos de estado HTTP se puede realizar utilizando la clase ResponseEntity, que permite devolver una
respuesta con el código de estado correspondiente.
POST: El método POST se utiliza para enviar datos al servidor y crear un nuevo recurso. Se utiliza cuando se desea agregar
información al servidor
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
// Lógica para crear un nuevo usuario en el servidor
User createdUser = userService.createUser(user);
return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
}
}
PUT: El método PUT se utiliza para enviar datos al servidor y actualizar un recurso existente. Se utiliza para modificar información
en el servidor.
@RestController
@RequestMapping("/api/users")
public class UserController {
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id,
@RequestBody User user) {
// Lógica para actualizar un usuario existente en el servidor
User updatedUser = userService.updateUser(id, user);
return ResponseEntity.ok(updatedUser);
}
}
DELETE: El método DELETE se utiliza para eliminar un recurso existente en el servidor.
@RestController
@RequestMapping("/api/users")
public class UserController {
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
// Lógica para eliminar un usuario por su ID
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}
Los códigos de estado HTTP son números de tres dígitos que se envían en la respuesta del servidor para indicar el resultado de una
solicitud. Proporcionan información adicional sobre el estado de la solicitud y permiten al cliente interpretar y manejar
adecuadamente la respuesta.
200 OK: Indica que la solicitud se ha procesado correctamente y se devuelve una respuesta exitosa.
201 Created: Indica que se ha creado un nuevo recurso como resultado de la solicitud.
400 Bad Request: Indica que la solicitud del cliente es incorrecta o no se puede procesar.
404 Not Found: Indica que el recurso solicitado no se ha encontrado en el servidor.
500 Internal Server Error: Indica que se produjo un error en el servidor al procesar la solicitud.
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
if (user != null) {
return ResponseEntity.ok(user);
} else {
return ResponseEntity.notFound().build();
}
}
}
Módulo 2: Manejo de parámetros en las peticiones
4 Parámetros de la petición
Introducción a los parámetros de URL: Los parámetros de URL son valores que se pasan en la propia URL y se utilizan para
identificar recursos o proporcionar información adicional.
Uso de la anotación @PathVariable en Spring: La anotación @PathVariable se utiliza para mapear y obtener valores de
parámetros de URL en los controladores de Spring.
@GetMapping("/{id}")
public String obtenerRecurso(@PathVariable int id) {
http://localhost:8080/recursos/{id}
http://localhost:8080/recursos/1
El manejo de parámetros en las peticiones HTTP es fundamental para enviar y recibir datos entre el cliente y el servidor en
el desarrollo web. Los parámetros permiten enviar información adicional junto con la solicitud y pueden ubicarse en
diferentes partes de la petición, como la URL, el cuerpo de la petición o las cabeceras.
@RequestParam se utiliza para vincular los parámetros de una solicitud HTTP a los parámetros de un método en un
controlador de Spring. Estos parámetros se pasan como parte de la URL de la solicitud HTTP, generalmente como parámetros
de consulta (query parameters) o como campos en un formulario. Por ejemplo, en la URL "http://ejemplo.com/mi_ruta?
parametro1=valor1¶metro2=valor2", los parámetros "parametro1" y "parametro2" pueden vincularse a los parámetros
del método usando @RequestParam.
@RestController
@RequestMapping("/productos")
public class ProductoController {
@GetMapping("/detalle")
public String obtenerDetalleProducto(@RequestParam("id") int id) {
// Lógica para obtener los detalles del producto con el ID proporcionado
return "Detalles del producto con ID " + id;
}
}
Por otro lado, @PathParam se utiliza para vincular segmentos de una URL a los parámetros de un método en un controlador de Spring.
Estos segmentos se especifican como parte de la ruta de la URL y se identifican mediante llaves {}. Por ejemplo, en la URL
"http://ejemplo.com/mi_ruta/{id}", el segmento "{id}" puede vincularse a un parámetro del método usando @PathParam.
En resumen, la diferencia principal radica en cómo se pasan los datos en la URL. @RequestParam se utiliza para parámetros de consulta o
campos de formulario, mientras que @PathParam se utiliza para segmentos de la ruta URL. Ambas anotaciones son útiles en diferentes
escenarios y se seleccionan según la forma en que se estructura y se pasan los datos en una solicitud HTTP.
@RestController
@RequestMapping("/productos")
public class ProductoController {
@GetMapping("/detalle/{id}")
public String obtenerDetalleProducto(@PathVariable("id") int id) {
// Lógica para obtener los detalles del producto con el ID proporcionado
return "Detalles del producto con ID " + id;
}
}
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}/{orderId}")
public ResponseEntity<String> getOrderDetails(
@PathVariable Long id,
@PathVariable String orderId
){
// Lógica para obtener los detalles de la orden para el usuario con el ID y el ID de la orden especificados
String orderDetails = "Detalles de la orden: " + orderId + " para el usuario con ID: " + id;
return ResponseEntity.ok(orderDetails);
}
}
2.2. Parámetros en el cuerpo de la petición:
Introducción a los parámetros en el cuerpo de la petición: Los parámetros en el cuerpo de la petición se utilizan para enviar datos más
complejos o grandes, como objetos JSON, en la solicitud.
Uso de la anotación @RequestBody en Spring: La anotación @RequestBody se utiliza para recibir y convertir el cuerpo de la petición
en un objeto Java en los controladores de Spring.
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@PostMapping
public ResponseEntity<Void> createProduct(@RequestBody Product product) {
productService.createProduct(product);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Autowired
private ProductService productService;
@PutMapping("/bulk-update")
public ResponseEntity<Void> bulkUpdateProducts(@RequestBody List<Product> products) {
productService.bulkUpdateProducts(products);
return ResponseEntity.ok().build();
}
}
parámetros en las cabeceras de la petición:
Cuando se realiza una solicitud HTTP, además de la URL y el cuerpo de la petición, también se pueden enviar cabeceras (headers) que
contienen información adicional o metadatos sobre la solicitud. Las cabeceras proporcionan detalles importantes sobre la solicitud,
como el tipo de contenido aceptado, el tipo de autenticación requerida, las preferencias de idioma, entre otros. Los parámetros en
las cabeceras de la petición se utilizan para enviar y recibir esta información adicional.
En Spring, la anotación @RequestHeader se utiliza para obtener y utilizar los valores de las cabeceras de la petición en los
controladores. Al aplicar la anotación @RequestHeader a un parámetro de un método de controlador, Spring asignará
automáticamente el valor de la cabecera correspondiente a ese parámetro.
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<String> getUserAgent(@PathVariable Long id, @RequestHeader("User-Agent") String userAgent) {
// Lógica para utilizar el valor del User-Agent en la solicitud
return ResponseEntity.ok("User-Agent: " + userAgent);
}
}
Crear un controlador que obtenga y utilice un valor de una cabecera específica para realizar una acción personalizada.
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public ResponseEntity<String> createUser(@RequestBody User user, @RequestHeader("X-Custom-Header") String customHeaderValue) {
// Lógica para crear un nuevo usuario utilizando el valor de la cabecera personalizada
return ResponseEntity.ok("Creación exitosa. Valor de la cabecera personalizada: " + customHeaderValue);
}
}
Implementar un controlador que verifique si ciertas cabeceras están presentes en la solicitud y realice diferentes acciones en función de eso.
@RestController
@RequestMapping("/api/products")
public class ProductController {
@GetMapping("/{id}")
public ResponseEntity<String> getProductDetails(@PathVariable Long id, HttpServletRequest request) {
if (request.getHeader("Authorization") != null && request.getHeader("Content-Type") != null) {
// Lógica para realizar acciones específicas si las cabeceras de autorización y tipo de contenido están presentes
return ResponseEntity.ok("Cabeceras presentes. Detalles del producto con ID: " + id);
} else {
// Lógica para manejar el caso cuando las cabeceras requeridas no están presentes
return ResponseEntity.badRequest().body("Cabeceras faltantes");
}
}
}
Módulo 3: Validación de datos en los controladores
En este módulo, se enseña cómo validar los datos recibidos en las solicitudes en los controladores de Spring Boot.
La validación de datos de entrada es un proceso importante para garantizar la integridad y la calidad de los datos que se reciben en una
aplicación. En el contexto de las peticiones en Spring, esto implica asegurarse de que los datos proporcionados cumplen con ciertos criterios
antes de procesarlos.
Una forma común de realizar la validación de datos de entrada en Spring es mediante el uso de anotaciones de validación. Spring proporciona
un conjunto de anotaciones que se pueden aplicar a los parámetros de los controladores para validarlos. Algunas de las anotaciones de
validación más utilizadas son:
@PostMapping("/users")
public ResponseEntity<String> createUser(@Valid @RequestBody User user) {
_userservice.grabar(user);
return ResponseEntity.ok("Usuario creado exitosamente");
}
}
En el código anterior, se utiliza la anotación @Valid en el parámetro userDto para indicarle a Spring que debe realizar la validación del
objeto UserDto utilizando las anotaciones de validación aplicadas en sus campos. Si alguna validación falla, Spring generará
automáticamente una respuesta de error.
@NotNull
Para definir las anotaciones de validación en el objeto UserDto, puedes private String name;
hacer lo siguiente:
@NotEmpty
@Email
private String email;
// Getters y setters
}
Módulo 4: Manejo de
excepciones en los
controladores
En este módulo, se explora cómo manejar excepciones en los controladores de
Spring Boot y cómo devolver respuestas adecuadas en caso de errores.
Manejo de excepciones:
El manejo de excepciones es un aspecto crítico en el desarrollo de aplicaciones, ya que permite controlar situaciones inesperadas y
manejarlas de forma adecuada. En el contexto de los controladores en Spring, el manejo de excepciones implica capturar y procesar las
excepciones que se generan durante la ejecución de una petición.
En Spring, se pueden manejar las excepciones en los controladores utilizando anotaciones como @ExceptionHandler. Esta anotación se
coloca en métodos dentro del controlador y se utiliza para capturar excepciones específicas y proporcionar una respuesta de error
personalizada.
@RestController
public class UserController { @ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<String>
@GetMapping("/users/{id}") handleUserNotFoundException(UserNotFoundException e) {
public ResponseEntity<UserDto> getUser(@PathVariable("id") Long return ResponseEntity.status(HttpStatus.NOT_FOUND).body("El usuario
userId) { no existe");
// Obtener los datos del usuario }
try {
UserDto userDto = userService.getUserById(userId); @ExceptionHandler(Exception.class)
return ResponseEntity.ok(userDto); public ResponseEntity<String> handleException(Exception e) {
} catch (UserNotFoundException e) { return
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error
} catch (Exception e) { interno del servidor");
return }
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null); }
}
}
Módulo 5: Uso de anotaciones avanzadas en los
controladores
En este módulo, se exploran anotaciones avanzadas disponibles en los controladores de Spring Boot para realizar acciones específicas, como
la autenticación y la autorización.
Uso de anotaciones avanzadas en los controladores:
En Spring Boot, existen anotaciones avanzadas disponibles en los controladores que permiten realizar acciones
específicas, como la autenticación y la autorización. Estas anotaciones proporcionan una forma más fácil y declarativa de
implementar características de seguridad en una aplicación.
@PreAuthorize: Esta anotación se utiliza para aplicar una lógica de autorización antes de que se ejecute un método del controlador. Puede
basarse en expresiones SpEL (Spring Expression Language) para evaluar condiciones de autorización y decidir si se permite o se deniega el
acceso al método.
@PostAuthorize: Esta anotación se utiliza para aplicar una lógica de autorización después de que se ejecute un método del controlador. Al
igual que @PreAuthorize, puede utilizar expresiones SpEL para evaluar condiciones de autorización y decidir si se permite o se deniega el
acceso al resultado del método.
@Secured: Esta anotación se utiliza para aplicar una lógica de autorización basada en roles de usuario. Puedes especificar uno o varios roles
permitidos para acceder a un método del controlador. Si el usuario actual no tiene ninguno de los roles especificados, se denegará el acceso.
@RolesAllowed: Esta anotación es similar a @Secured y se utiliza para aplicar una lógica de autorización basada en roles de usuario. Puedes
especificar uno o varios roles permitidos para acceder a un método del controlador. Sin embargo, @RolesAllowed es parte de la
especificación de seguridad de Java EE y requiere una configuración adicional en Spring Boot para que funcione correctamente
@RestController
public class MyController {
@GetMapping("/public")
public String publicEndpoint() {
return "Esta es una ruta pública";
}
@GetMapping("/private")
@PreAuthorize("isAuthenticated()")
public String privateEndpoint() {
return "Esta es una ruta privada que requiere autenticación";
}
}
Módulo 6: Introducción a ResponseEntity
Comprender los conceptos básicos de ResponseEntity y su importancia en los controladores de Spring Boot.
ResponseEntity es una clase proporcionada por Spring Framework que representa una respuesta HTTP. Se utiliza para construir y
enviar respuestas personalizadas desde los controladores de Spring Boot. Algunos conceptos clave para comprender ResponseEntity
son:
1.Tipo de cuerpo (Body Type): Es el tipo de dato que se incluye en el cuerpo de la respuesta. Puede ser cualquier objeto, como una
cadena de texto, un objeto JSON, una lista, etc.
2.Código de estado (Status Code): Es un código numérico que indica el estado de la respuesta HTTP. Algunos ejemplos comunes
incluyen 200 para "OK" (éxito), 404 para "No encontrado" y 500 para "Error del servidor".
3.Encabezados (Headers): Son metadatos adicionales que se pueden adjuntar a la respuesta HTTP, como el tipo de contenido, la
codificación, la longitud del contenido, entre otros.
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class WelcomeController {
@GetMapping("/welcome")
public ResponseEntity<String> welcome() {
String message = "¡Bienvenido a mi aplicación Spring Boot!";
return ResponseEntity.status(HttpStatus.OK).body(message);
}
}
Módulo 7: Personalización de la
respuesta
@RestController
public class UserController {
@PostMapping("/users")
public ResponseEntity<String> createUser() {
// Lógica para crear un usuario
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HeaderController {
@GetMapping("/customHeaders")
public ResponseEntity<String> customHeaders() {
String mensaje = "Respuesta con encabezados personalizados";
Cuando trabajas con servicios web, es común que necesites enviar respuestas en formato JSON, ya que es un formato ampliamente
utilizado para intercambiar datos en aplicaciones web. En Spring Boot, puedes utilizar ResponseEntity para enviar respuestas con
formato JSON desde tus controladores.
Para enviar una respuesta JSON utilizando ResponseEntity, necesitarás un convertidor JSON configurado en tu aplicación. Spring
Boot proporciona integración con bibliotecas populares como Jackson, Gson o JSON-B, lo que facilita la conversión de objetos Java
en JSON y viceversa.
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/productos")
public class ProductController {
@GetMapping("/{id}")
public ResponseEntity<Product> getProductById(@PathVariable("id") int id) {
// Supongamos que aquí obtienes el producto por su ID desde la base de datos o algún otro origen de datos.
Product product = new Product();
product.setNombre("Producto Ejemplo");
product.setPrecio(9.99);
product.setDescripcion("Este es un producto de ejemplo.");
return ResponseEntity.status(HttpStatus.OK).body(product);
}
}
Manipulación de códigos de estado en las respuestas es un aspecto importante al utilizar ResponseEntity en Spring Boot. Permite
establecer el código de estado adecuado en función de diferentes escenarios en tu aplicación. A continuación, se proporciona una
descripción ampliada y un ejercicio práctico para comprender mejor este concepto.
Cuando construyes una API, es esencial comunicar el estado de una solicitud al cliente de manera adecuada. Los códigos de estado
HTTP proporcionan información sobre el resultado de una solicitud realizada al servidor. ResponseEntity te permite establecer estos
códigos de estado en tus respuestas.
@RestController
public class EjemploController {
@DeleteMapping("/recurso/{id}")
public ResponseEntity<String> eliminarRecurso(@PathVariable String id) {
// Lógica para verificar si el recurso existe
boolean recursoExistente = verificarRecursoExistente(id);
if (recursoExistente) {
// Lógica para eliminar el recurso
eliminarRecurso(id);
return new ResponseEntity<>("Recurso eliminado correctamente",
HttpStatus.OK);
} else {
return new ResponseEntity<>("Recurso no encontrado",
HttpStatus.NOT_FOUND);
}
}
private boolean verificarRecursoExistente(String id) {
// Lógica para verificar si el recurso existe en la base de datos o en algún
otro almacenamiento
// Retorna true si el recurso existe, false si no existe
return false;
}
Descripción:
En una aplicación web, a menudo es necesario enviar archivos adjuntos al cliente, como imágenes, documentos, hojas de cálculo, etc.
Spring Boot ofrece la clase ResponseEntity para facilitar el envío de archivos adjuntos como parte de la respuesta HTTP. Al utilizar
ResponseEntity, puedes establecer el contenido del archivo, el encabezado Content-Disposition y otros encabezados relevantes para
asegurarte de que el archivo se descargue correctamente por el cliente.
import java.io.IOException;
@RestController
public class AdjuntoController {
@GetMapping("/descargar-adjunto")
public ResponseEntity<byte[]> descargarAdjunto() throws IOException {
ClassPathResource resource = new
ClassPathResource("archivos/nombre_del_archivo");