JavaRush /Курсы /Модуль 5. Spring /Аннотации @RequestBody, @ResponseBody

Аннотации @RequestBody, @ResponseBody

Модуль 5. Spring
8 уровень , 3 лекция
Открыта

Когда мы создаём REST API, часто нам нужно обрабатывать данные, которые передаются в запросах. Например, создаём новую запись или обновляем существующую. Эти данные обычно передаются в теле HTTP-запроса. Также, когда сервер отвечает клиенту, мы отправляем данные обратно, например, в формате JSON. В этот момент на сцену выходят аннотации @RequestBody и @ResponseBody.

  • @RequestBody: помогает "извлечь" данные из тела HTTP-запроса и преобразовывает их в объект Java, который мы можем легко использовать в коде.
  • @ResponseBody: автоматически преобразовывает объект Java в JSON (или другой формат) и отправляет его в тело HTTP-ответа.

Это похоже на "телепортацию данных" между клиентом и сервером. Вы передаёте JSON на сервер, и он магическим образом превращается в нормальный Java-объект. А сервер, в свою очередь, возвращает объект, который чудесным образом становится JSON.


Работа с телом запроса: @RequestBody

Spring Boot использует библиотеку Jackson (по умолчанию) для преобразования данных. Когда приходит HTTP-запрос с JSON, аннотация @RequestBody говорит Spring: "Эй, возьми тело запроса, распарси его и передай мне объект Java!".

Допустим, у нас есть сущность User:


public class User {
    private String name;
    private int age;

    // Геттеры и сеттеры
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

Мы хотим написать контроллер, который будет получать объект User в теле запроса:


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

    @PostMapping
    public String createUser(@RequestBody User user) {
        // Логируем входящие данные
        System.out.println("Получен пользователь: " + user.getName() + ", возраст: " + user.getAge());
        return "Пользователь " + user.getName() + " успешно создан!";
    }
}

Клиент отправляет POST-запрос:


{
    "name": "Иван",
    "age": 30
}

И на сервере это преобразуется в объект User. Никакого дополнительного кода для парсинга JSON не требуется — о всём заботится Spring.


Валидация данных

Иногда переданные данные могут быть недопустимыми. Например, пустое имя или возраст меньше нуля. В таких случаях мы можем использовать аннотацию @Valid для автоматической валидации:


import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;

public class User {
    @NotNull(message = "Имя не должно быть пустым")
    private String name;

    @Min(value = 0, message = "Возраст не может быть отрицательным")
    private int age;

    // Геттеры и сеттеры
}

И в контроллере:


@PostMapping
public String createUser(@Valid @RequestBody User user) {
    return "Пользователь " + user.getName() + " успешно создан!";
}

Если клиент отправит некорректные данные, например:


{
    "name": "",
    "age": -1
}

Сервер вернёт ошибку 400 Bad Request с подробностями:


{
    "timestamp": "2023-10-22T10:12:45.123+00:00",
    "status": 400,
    "error": "Bad Request",
    "messages": [
        "Имя не должно быть пустым",
        "Возраст не может быть отрицательным"
    ]
}

Работа с ответами: @ResponseBody

Когда нам нужно отправить данные клиенту, @ResponseBody приходит на помощь. Эта волшебная аннотация подсказывает Spring, что объект Java должен превратиться в JSON (или другой формат) и стать частью ответа.

А знаете что интересно? Если вы используете @RestController, то Spring автоматически добавит @ResponseBody ко всем методам контроллера. Именно поэтому REST-контроллеры пишутся быстрее и элегантнее — Spring уже позаботился об этом за вас.

Продолжим работу с UserController. Теперь добавим метод для получения пользователя:


@GetMapping("/{id}")
public @ResponseBody User getUser(@PathVariable int id) {
    // Заглушка: вернём фиктивного пользователя
    User user = new User();
    user.setName("Иван");
    user.setAge(30);
    return user;
}

Клиент отправляет GET-запрос:


GET /users/1

Ответ сервера:


{
    "name": "Иван",
    "age": 30
}

Советы по работе с @ResponseBody

  1. Вы можете возвращать не только объекты, но и коллекции. Например:

@GetMapping
public List<User> getAllUsers() {
    List<User> users = new ArrayList<>();
    User user1 = new User();
    user1.setName("Иван");
    user1.setAge(30);
    users.add(user1);

    User user2 = new User();
    user2.setName("Анна");
    user2.setAge(25);
    users.add(user2);

    return users;
}

Ответ сервера:


[
    {
        "name": "Иван",
        "age": 30
    },
    {
        "name": "Анна",
        "age": 25
    }
]

Особенности работы аннотации

Если вы используете аннотацию @ResponseBody с обычным @Controller (не @RestController), не забудьте добавить её ко всем методам, которые должны возвращать данные в HTTP-ответе. Например:


@Controller
public class MyController {

    @GetMapping("/hello")
    public @ResponseBody String sayHello() {
        return "Привет!";
    }
}

Типичные ошибки при использовании @RequestBody и @ResponseBody

Очень важно понимать, как работают эти аннотации, чтобы избежать ошибок. Например:

  1. Ошибка десериализации: если JSON, отправленный клиентом, не соответствует структуре объекта, Spring бросит исключение. Например, если клиент забыл поле "name", то вы получите ошибку HttpMessageNotReadableException.
    • Решение: Убедитесь, что структура JSON согласуется с моделью объекта.
  2. Отказ от использования аннотации @Valid: без валидации вы можете получить некорректные данные в базе. Используйте @Valid и обработчики ошибок.
  3. Игнорирование уровней логирования: логируйте JSON-запросы и ответы — это спасёт ваше время при отладке.

Практическое применение

@RequestBody и @ResponseBody — это два кита, на которых держится REST API. Они берут на себя всю головную боль по обработке JSON — больше никакого ручного парсинга и форматирования! В реальных проектах эти аннотации становятся вашими верными помощниками при работе с данными, их проверкой и преобразованием.

Невозможно представить современный REST API без этих аннотаций — это как пытаться писать код без IDE. Освоив их, вы сможете создавать элегантные и надежные API. И, конечно, не забывайте тестировать свои эндпоинты — но это уже совсем другая история!

Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Артём Уровень 112
18 сентября 2025
Аннотация @NotNull пустую строку "" как раз пропустит, потому что это не null. Чтобы не пропустило, надо использовать @NonBlank . По умолчанию JSON с сообщением об ошибке никаких кастомных сообщений не содержит из соображений безопасности. Чтобы их там увидеть, надо в application.properties добавить server.error.include-binding-errors=always , правда, добавится ещё куча всякого разного, что не захочется никому показывать.