23 апреля 2018
Тэги: Spring Boot rest SQL Java
В статье Работа с БД в Spring Boot на примере postgresql мы узнали как читать данные из БД. Но чтение данных - это лишь малая часть всех операций, которые встречаются в типичном java-приложении. Теперь попробуем создать полноценный rest-интерфейс для добавления новых записей, их модификации и удаления.
За основу возьмём наше приложение из указанной статьи. Оно состоит из трёх слоёв: dao (работа с БД), бизнес-логика приложения (service) и сам rest-интерфейс (controller), который обрабатывает входящий json и генерирует исходящий.
Начнём с доработки dao-слоя (интерфейс ProfileDao), где до сих пор был только один метод чтения данных.
При добавлении новой записи нам достаточно всего три поля. id будет сгенерирован в БД автоматически.
В реализацию интерфейса dao (ProfileDaoImpl) добавим sql-запросы в виде констант, которые принято размещать в начале класса:
Имена параметров, которые мы будем подставлять в sql-запрос, начинаются с двоеточия.
Вот реализация добавления записи в БД:
Всё предельно просто: сначала собираем параметры, затем передаём их вместе с запросом в метод jdbcTemplate.update(), который вопреки своему названию отвечает вообще за любые изменения данных (и insert, и update, и delete). Обратите внимание, что jdbcTemplate у нас имеет тип NamedParameterJdbcTemplate - именно он позволяет использовать именованные параметры. Иначе пришлось бы писать знаки вопроса.
Перейдём к сервисному слою. Интерфейс ProfileService не отличается оригинальностью:
Его реализация в ProfileServiceImpl. Здесь по сути только вызываем dao-метод:
Согласно архитектуре restful-сервисов, чтение данных мы делаем при помощи GET-запросов, а создание - при помощи POST. Также хотелось бы отметить, что у GET-запроса не может быть тела запроса (body), все его параметры перечисляются в строке запроса. А POST-запрос может иметь тело, в которое мы будем помещать целевой json.
Перейдём к нашему контроллеру ProfileController и добавим в него метод создания профиля.
В качестве аргумента метод принимает модель запроса ProfileRequest:
Эта модель представляет собой ровно тот объект, который мы ожидаем увидеть в теле запроса. Имена полей в json должны совпадать с именами полей в классе (при желании это можно переопределить дополнительной аннотацией). Дополнительно накладываем ограничения из пакета javax.validation.constraints на каждое поле.
Аннотация @NotNull применима для ссылочных типов и означает обязательность этого поля в запросе. Обратите внимание, что тут мы специально используем ссылочный Integer, который допускает null, а не примитивный int, который по умолчанию равен нулю. Ссылочный числовой тип вместе с @NotNull позволяет проверять обязательность числовых типов.
Аннотация @Min говорит сама за себя и ограничивает числовые типы снизу. Тем самым мы никогда не допустим, чтобы нам передали отрицательное число в качестве возраста.
Чтобы эти проверки работали для входящего json, параметр метода надо снабдить аннотацией @Valid, а чтобы именно в этот класс был преобразован json, также добавляем @ResponseBody. Внутри просто вызываем сервисный слой.
Аннотация @PostMapping указывает на то, что это обработчик POST-запроса. В скобках можно указать урл, но в данном случае мы его не указали, поэтому запрос надо будет кидать по тому адресу, который указан на уровне контроллера, то есть /profile. @ResponseStatus показывает, какой http-код нужно вернуть в ответ. В данном случае мы опять следуем rest-архитектуре и возвращаем код 201 - «Created».
Теперь мы готовы к тому, чтобы выполнить rest-запрос на создание новой записи в БД. Запускаем приложение и отравляем указанный POST-запрос по адресу http://127.0.0.1:8080/profile. В http-заголовках обязательно указываем Content-Type: application/json.
В ответ в случае успеха получаем http-статус 201. Если же мы попытаемся нарушить наши ограничения по полям, то получим json с подробным описанием ошибки.
Таким образом, Spring Boot позволяет буквально за 5 минут создать полноценный обработчик POST-запроса с валидацией входящих параметров.
Kotlin, Java, Java 11, Java 10, Java 9, Java 8, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Hibernate, Collections, Stream API, многопоточность, Apache, maven, gradle, JUnit, ООП, алгоритмы, головоломки, rest