CodeGym /Cursos /Módulo 5. Spring /Formación de respuestas: @ResponseBody, @ModelAttribute

Formación de respuestas: @ResponseBody, @ModelAttribute

Módulo 5. Spring
Nivel 7 , Lección 4
Disponible

En el desarrollo web hay dos direcciones en las que se mueven los datos:

  1. Cliente → Servidor (procesamiento de peticiones).
  2. Servidor → Cliente (formación de respuestas).

Si ya hemos visto la primera dirección, la segunda merece nuestra atención. Vamos a ver cómo el servidor puede "responder" al cliente y por qué eso importa para que la interacción funcione.

Opciones de respuesta

  1. Páginas HTML.
    • El servidor devuelve código HTML que el navegador renderiza para el usuario.
  2. JSON/XML.
    • Datos serializados para clientes (por ejemplo en una REST API).
  3. Archivos u otros recursos.
    • Por ejemplo, imágenes, PDF o archivos ZIP.

En Spring MVC podemos formar respuestas de forma flexible gracias a su potente sistema de anotaciones e instrumentos.


Anotación @ResponseBody

Si vienes del mundo de las REST API, la frase "respuestas JSON" te sonará a música. Esta anotación se encarga de enviar datos en formato JSON o XML desde el controlador al cliente.

En esencia, @ResponseBody le dice a Spring: "Basta de hacer esos espectáculos bonitos con páginas HTML. Simplemente manda los datos al cliente, sin dramatismo". Es decir, cancela la resolución de vistas (view resolution), y en su lugar devuelve los datos directamente en la respuesta HTTP.

Ejemplo: Envío de respuesta JSON

Aquí tienes el ejemplo más básico:


@RestController
@RequestMapping("/api")
public class UserController {

    @GetMapping("/user")
    public User getUser() {
        return new User(1, "John Doe");
    }
}

Aquí usamos @RestController, que en esencia es un atajo de @Controller + @ResponseBody. Eso significa que cada método devuelve una respuesta JSON. Si devuelves un objeto, Spring lo transformará automáticamente a JSON (serializará) gracias a la librería Jackson integrada.

¿Cómo funciona? Spring sabe serializar objetos a JSON gracias a la librería Jackson. Está incluida "out of the box", así que no necesitas movimientos extra. Pero si quieres serializar a XML, tendrás que hacer algún ajuste.

Ejemplo: Uso de @ResponseBody sin @RestController

Si por alguna razón estás usando un controlador normal en vez de @RestController, no pasa nada. Simplemente añade @ResponseBody al método.


@Controller
@RequestMapping("/api")
public class UserController {

    @ResponseBody
    @GetMapping("/user")
    public User getUser() {
        return new User(1, "Jane Doe");
    }
}

Esta anotación indica a Spring que los datos deben devolverse directamente, y no buscar una vista.

¿Se puede devolver algo más que JSON?

Claro. Si quieres devolver, por ejemplo, una cadena u otro tipo de dato, @ResponseBody lo hará con gusto.


@Controller
@RequestMapping("/api")
public class ExampleController {

    @ResponseBody
    @GetMapping("/hello")
    public String sayHello() {
        return "Hello, Spring MVC!";
    }
}

El cliente recibirá simplemente la cadena: Hello, Spring MVC!.

Errores típicos al usar @ResponseBody

  1. Error: "Cannot serialize object". Esto sucede si el objeto no puede convertirse a JSON. Por ejemplo, no tiene public getters, o te olvidaste de incluir Jackson.
  2. Devolver HTML por accidente. Si olvidas @ResponseBody o usas @Controller sin ella, Spring puede intentar buscar una página HTML cuyo nombre coincida con el valor devuelto (por ejemplo, "user" para el método getUser).

Anotación @ModelAttribute

Si @ResponseBody es tu mejor amigo para las REST API, @ModelAttribute es imprescindible para trabajar con el MVC clásico, donde se usan HTML y plantillas del lado del servidor.

La anotación @ModelAttribute te ayuda a pasar datos del controlador a la vista. Carga un objeto en el modelo (sí, nos referimos a org.springframework.ui.Model!), para luego pasarlo a la plantilla.

Ejemplo: pasar un objeto a la vista

Supongamos que tenemos una página HTML que muestra la información de un usuario. Primero hay que pasar los datos:


@Controller
@RequestMapping("/users")
public class UserController {

    @GetMapping("/profile")
    public String userProfile(Model model) {
        User user = new User(1, "Jane Doe");
        model.addAttribute("user", user);
        return "userProfile";
    }
}

Aquí añadimos el objeto user al modelo y luego devolvemos el nombre de la vista (userProfile), que lo mostrará. La vista puede ser, por ejemplo, una plantilla Thymeleaf.

Uso de @ModelAttribute

¿Pero para qué agregar manualmente al modelo si existe @ModelAttribute?


@Controller
@RequestMapping("/users")
public class UserController {

    @ModelAttribute("user")
    public User getUser() {
        return new User(1, "Jane Doe");
    }

    @GetMapping("/profile")
    public String userProfile() {
        return "userProfile";
    }
}

Spring llamará al método con @ModelAttribute automáticamente en cualquier petición al controlador, y el objeto se añadirá al modelo con el nombre indicado (user). Esto reduce el código y mantiene tu controlador más limpio.


Ejemplo: trabajar con formularios

@ModelAttribute también se usa para enlazar los datos del formulario a objetos Java.


@Controller
@RequestMapping("/users")
public class UserController {

    @GetMapping("/register")
    public String showRegistrationForm(Model model) {
        model.addAttribute("user", new User());
        return "register";
    }

    @PostMapping("/register")
    public String processRegistration(@ModelAttribute("user") User user) {
        System.out.println("Registered user: " + user);
        return "registrationSuccess";
    }
}
  • Petición GET muestra el formulario de registro con un objeto User vacío.
  • Petición POST enlaza automáticamente los datos del formulario con el objeto User.

Errores típicos al usar @ModelAttribute

  1. Error: "NullPointerException". Si te olvidas de añadir el objeto al modelo, la vista no podrá renderizar los datos.
  2. Error de enlace de datos. Si tienes un objeto complejo y los datos del formulario no pueden asignarse, Spring lanzará un error. Asegúrate de que todos los campos del formulario coincidan con los campos del objeto.

¿Cuándo usar @ResponseBody y @ModelAttribute?

Anotación Cuándo usar
@ResponseBody Cuando necesites devolver JSON/XML o una cadena
@ModelAttribute| Cuando trabajas con formularios HTML o plantillas

Ahora estás armado con los conocimientos sobre cómo formar respuestas en Spring MVC. Recuerda: @ResponseBody es la mejor opción para REST API, y @ModelAttribute te salvará en el mundo de formularios y la generación de HTML del lado del servidor.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION