Обработка данных формы
Этот урок освещает процесс использования Spring для создания и отправки web формы.
Что вы создадите
В этом уроке вы создадите web форму, которая будет доступна по URL:
http://localhost:8080/greeting
При просмотре этой страницы отобразится форма. Вы сможете отправить сообщение, заполнив поля id и content . Результирующая страница будет отображена, когда форма будет отправлена.
Что вам потребуется
- Примерно 15 минут свободного времени
- Любимый текстовый редактор или IDE
- JDK 6 и выше
- Gradle 1.11+ или Maven 3.0+
- Вы также можете импортировать код этого урока, а также просматривать web-страницы прямо из Spring Tool Suite (STS), собственно как и работать дальше из него.
Как проходить этот урок
Как и большинство уроков по Spring, вы можете начать с нуля и выполнять каждый шаг, либо пропустить базовые шаги, которые вам уже знакомы. В любом случае, вы в конечном итоге получите рабочий код.
Чтобы начать с нуля, перейдите в Настройка проекта.
- Загрузите и распакуйте архив с кодом этого урока, либо кнонируйте из репозитория с помощью Git: git clone https://github.com/spring-guides/gs-handling-form-submission.git
- Перейдите в каталог gs-handling-form-submission/initial
- Забегая вперед, создайте web контроллер
Когда вы закончите, можете сравнить получившийся результат с образцом в gs-handling-form-submission/complete .
Настройка проекта
Для начала вам необходимо настроить базовый скрипт сборки. Вы можете использовать любую систему сборки, которая вам нравится для сборки проетов Spring, но в этом уроке рассмотрим код для работы с Gradle и Maven. Если вы не знакомы ни с одним из них, ознакомьтесь с соответсвующими уроками Сборка Java-проекта с использованием Gradle или Сборка Java-проекта с использованием Maven.
Создание структуры каталогов
В выбранном вами каталоге проекта создайте следующую структуру каталогов; к примеру, командой mkdir -p src/main/java/hello для *nix систем:
└── src └── main └── java └── hello
Создание файла сборки Gradle
Ниже представлен начальный файл сборки Gradle. Файл pom.xml находится здесь. Если вы используете Spring Tool Suite (STS), то можете импортировать урок прямо из него.
Если вы посмотрите на pom.xml , вы найдете, что указана версия для maven-compiler-plugin. В общем, это не рекомендуется делать. В данном случае он предназначен для решения проблем с нашей CI системы, которая по умолчанию имеет старую(до Java 5) версию этого плагина.
buildscript < repositories < maven < url "http://repo.spring.io/libs-release" >mavenLocal() mavenCentral() > dependencies < classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.8.RELEASE") >> apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'spring-boot' jar < baseName = 'gs-handling-form-submission' version = '0.1.0' >repositories < mavenLocal() mavenCentral() maven < url "http://repo.spring.io/libs-release" >> dependencies < compile("org.springframework.boot:spring-boot-starter-thymeleaf") testCompile("junit:junit") >task wrapper(type: Wrapper)
Spring Boot gradle plugin предоставляет множество удобных возможностей:
- Он собирает все jar’ы в classpath и собирает единое, исполняемое «über-jar», что делает более удобным выполнение и доставку вашего сервиса
- Он ищет public static void main() метод, как признак исполняемого класса
- Он предоставляет встроенное разрешение зависимостей, с определенными номерами версий для соответсвующих Spring Boot зависимостей. Вы можете переопределить на любые версии, какие захотите, но он будет по умолчанию для Boot выбранным набором версий
Создание web контроллера
В подходе Spring к построению web сайтов, HTTP запросы обрабатываются контроллером. Эти компоненты легко идентифицируются по @Controller аннотации. Ниже представленный GreetingController обрабатывает GET запросы для /greeting , возвращая название View , в данном случае это «greeting». View ответственнен за рендеринг HTML контента.
package hello; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller public class GreetingController < @RequestMapping(value="/greeting", method=RequestMethod.GET) public String greetingForm(Model model) < model.addAttribute("greeting", new Greeting()); return "greeting"; >@RequestMapping(value="/greeting", method=RequestMethod.POST) public String greetingSubmit(@ModelAttribute Greeting greeting, Model model) < model.addAttribute("greeting", greeting); return "result"; >>
Этот контроллер лаконичен и прост, но в нем много чего происходит. Давайте подробнее рассмотрим шаг за шагом.
Аннотация @RequestMapping позволяет вам связать HTTP запросы с определенными методами контроллера. В этом контроллере два метода и оба они относятся к /greeting . По умолчанию, @RequestMapping соответствует всем HTTP операциям, таким как GET , POST и так далее. Но в данном случае метод greetingForm() явно связан с GET , используя @RequestMapping(method=GET) , в то время как greetingSubmit() связан с POST через @RequestMapping(method=POST) . Эти соответствия позволяют контроллеру различать типы запросов к /greeting .
Метод greetingForm() использует объект Model для предоставления доступа к новому Greeting в шаблоне представления. Greeting объект в приведенном ниже коде содержит поля id и content , соответствующие полям формы в greeting представлении, и которые будут использованы для извлечения информации из формы.
package hello; public class Greeting < private long id; private String content; public long getId() < return id; >public void setId(long id) < this.id = id; >public String getContent() < return content; >public void setContent(String content) < this.content = content; >>
Реализация тела метода основана на View Technology, в данном случае на Thymeleaf, чтобы выполнять рендеринг HTML на стороне сервера. Thymeleaf парсит шаблон greeting.html , приведенный ниже, и вычисляет различные выражения для рендеринга формы.
Getting Started: Handing Form Submission Form
Выражение th:action=»@» направляет форму к POST запросу /greeting , в то время как выражение th:object=»$
Это то, за что отвечает контроллер, модель и представление для отображения формы. Теперь давайте рассмотрим процесс отправки формы. Как уже отмечалось выше, форма отправляется на /greeting , используя POST . Метод greetingSubmit() получает объект Greeting , который был заполнен формой. Затем он добавляет этот объект в модель для того, чтобы отправленные данные могли быть отображены в представлении result , как показано ниже. id представлен в выражении
» />
Getting Started: Handing Form Submission Result
" /> " /> Submit another message
Для наглядности, этот пример использует два отдельных шаблона представления для рендеринга формы и отображения отправленных данных; однако никто вам не мешает использовать одно представление для обеих целей.
Создание приложения исполняемым
Несмотря на то, что пакет этого сервиса может быть в составе web-приложения и WAR файлов, более простой подход, продемонстрированный ниже создает отдельное самостоятельное приложение. Вы упаковываете все в единый, исполняемый JAR-файл, который запускается через хорошо знакомый старый main() Java-метод. Попутно, вы используете поддержку Spring для встроенного Tomcat контейнера сервлетов как HTTP среду выполнения вместо развертывания на сторонний экземпляр.
package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; @ComponentScan @EnableAutoConfiguration public class Application < public static void main(String[] args) < SpringApplication.run(Application.class, args); >>
Метод main() передает управление вспомогательному классу SpringApplication , предоставляя Application.class как аргумент его run() методу. Это говорит Spring о том, чтобы прочитать аннотацию метаданных из Application и управлять им как компонентом в Spring Application Context.
Аннотация @ComponentScan сообщает Spring о запуске рекурсивного поиска в пакете hello и потомках классов, отмеченных прямо или косвенно Spring аннотацией @Component . При этом гарантируется, что Spring найдет и зарегистрирует GreetingController , потому что он отмечен @Controller , что в свою очередь является своего рода @Component аннотацией.
@EnableAutoConfiguration аннотация переключает на доступные по умолчанию настройки, основанные на содержимом вашего classpath. К примеру, т.к. приложение зависит от встраиваемой версии Tomcat(tomcat-embed-core.jar), то Tomcat сервер установлен и настроен по умолчанию от вашего имени. И также, т.к. приложение зависит от Spring MVC (spring-webmvc.jar), Spring MVC DispatcherServlet настроен и зарегистрирован за вас — web.xml не нужен! Автонастройка является мощным и гибким механизмом. Более подробно вы можете ознакомиться в API документации.
Сборка исполняемого JAR
Вы можете собрать единый исполняемый JAR-файл, который содержит все необходимые зависимости, классы и ресурсы. Это делает его легким в загрузке, версионировании и развертывании сервиса как приложения на протяжении всего периода разработки, на различных средах и так далее.
./gradlew build
Затем вы можете запустить JAR-файл:
java -jar build/libs/gs-handling-form-submission-0.1.0.jar
Если вы используете Maven, вы можете запустить приложение, используя mvn spring-boot:run , либо вы можете собрать приложение с mvn clean package и запустить JAR примерно так:
java -jar target/gs-handling-form-submission-0.1.0.jar
Процедура, описанная выше, создает исполняемый JAR. Вы также можете вместо него собрать классический WAR-файл.
Если вы используете Gradle, вы можете запустить ваш сервис из командной строки:
./gradlew clean build && java -jar build/libs/gs-handling-form-submission-0.1.0.jar
Если вы используете Maven, то можете запустить ваш сервис таким образом: mvn clean package && java -jar target/gs-handling-form-submission-0.1.0.jar .
Как вариант, вы можете запустить ваш сервис напрямую из Gradle примерно так:
./gradlew bootRun
С mvn — mvn spring-boot:run .
Выходные данные отображены. Сервис должен быть поднят и запущен через несколько секунд.
Тестирование сервиса
Теперь, когда web сайт запущен, перейдите по адресу http://localhost:8080/greeting, где вы увидите форму:

Отправьте id и message, чтобы посмотреть на результат:

Итог
Поздравляем! Вы только что использовали Spring для создания и отправки формы.
С оригинальным текстом урока вы можете ознакомиться на spring.io.
Добавление записи через POST-запрос в Spring Boot
В статье Работа с БД в Spring Boot на примере postgresql мы узнали как читать данные из БД. Но чтение данных – это лишь малая часть всех операций, которые встречаются в типичном java-приложении. Теперь попробуем создать полноценный rest-интерфейс для добавления новых записей, их модификации и удаления.
За основу возьмём наше приложение из указанной статьи. Оно состоит из трёх слоёв: работа с БД (repository), бизнес-логика приложения (service) и сам rest-интерфейс (controller), который обрабатывает входящий json и генерирует исходящий.
Репозиторий
Начнём с доработки репозитория (интерфейс ProfileRepository), где до сих пор был только один метод чтения данных. Добавим метод вставки записи в БД:
void insertProfile(String firstName, String secondName, int age);
При добавлении новой записи нам достаточно всего три поля. id будет сгенерирован в БД автоматически.
В реализацию интерфейса ProfileRepositoryImpl добавляем sql-запросы в виде констант, которые принято размещать в начале класса:
private static final String SQL_INSERT_PROFILE =
«insert into profile (first_name, last_name, age) values (:firstName, :lastName, :age)» ;
Имена параметров, которые мы будем подставлять в sql-запрос, начинаются с двоеточия.
Вот реализация добавления записи в БД:
@Override
public void insertProfile(String firstName, String lastName, int age) var params = new MapSqlParameterSource();
params.addValue( «firstName» , firstName);
params.addValue( «lastName» , lastName);
params.addValue( «age» , age);
jdbcTemplate.update( SQL_INSERT_PROFILE , params);
>
Всё предельно просто: сначала собираем параметры, затем передаём их вместе с запросом в метод jdbcTemplate.update(), который вопреки своему названию отвечает вообще за любые изменения данных (и insert, и update, и delete). Обратите внимание, что jdbcTemplate у нас имеет тип NamedParameterJdbcTemplate – именно он позволяет использовать именованные параметры. Иначе пришлось бы писать знаки вопроса.
Сервисный слой
Перейдём к сервисному слою. Интерфейс ProfileService не отличается оригинальностью:
void createProfile(String firstName, String secondName, int age);
Его реализация в ProfileServiceImpl. Здесь по сути только вызываем метод репозитория:
@Override
public void createProfile(String firstName, String secondName, int age) profileRepository.insertProfile(firstName, secondName, age);
>
Контроллер
Согласно архитектуре restful-сервисов, чтение данных мы делаем при помощи GET-запросов, а создание – при помощи POST. Также хотелось бы отметить, что у GET-запроса не может быть тела запроса (body), все его параметры перечисляются в строке запроса. А POST-запрос может иметь тело, в которое мы будем помещать целевой json.
Сперва нам нужно добавить в проект ещё одну зависимость spring-boot-starter-validation, которая позволяет валидировать входящие запросы:
Перейдём к нашему контроллеру ProfileController и добавим в него метод создания профиля.
@PostMapping
@ResponseStatus (HttpStatus. CREATED )
public void createProfile( @Valid @RequestBody ProfileRequest request) profileService.createProfile(
request.firstName(),
request.lastName(),
request.age()
);
>
В качестве аргумента метод принимает объект ProfileRequest, реализованный как record-class:
public record ProfileRequest(
@NotNull
String firstName,
@NotNull
String lastName,
@NotNull
@Min ( 1 )
Integer age
) >
Эта модель представляет собой ровно тот объект, который мы ожидаем в теле запроса. Имена полей в json должны совпадать с именами полей в классе (при желании это можно переопределить дополнительной аннотацией). Дополнительно накладываем ограничения из пакета javax.validation.constraints на каждое поле.
Аннотация @NotNull применима для ссылочных типов и означает обязательность этого поля в запросе. Обратите внимание, что тут мы специально используем ссылочный Integer, который допускает null, а не примитивный int, который по умолчанию равен нулю. Ссылочный числовой тип вместе с @NotNull позволяет проверять обязательность числовых типов.
Аннотация @Min говорит сама за себя и ограничивает числовые типы снизу. Тем самым мы никогда не допустим, чтобы нам передали отрицательное число в качестве возраста.
Чтобы эти проверки работали для входящего json, параметр метода надо снабдить аннотацией @Valid, а чтобы именно в этот класс был преобразован входящий json, также добавляем @RequestBody. Внутри просто вызываем сервисный слой.
Аннотация @PostMapping указывает на то, что это обработчик POST-запроса. В скобках можно указать относительный урл, но в данном случае мы его не указали, поэтому запрос надо будет кидать по тому адресу, который указан на уровне контроллера, то есть /profiles. @ResponseStatus показывает, какой http-код нужно вернуть в ответ. В данном случае мы опять следуем rest-соглашениям и возвращаем код 201 – «Created».
Теперь мы готовы к тому, чтобы выполнить rest-запрос на создание новой записи в БД. Запускаем приложение и отравляем указанный POST-запрос по адресу http://127.0.0.1:8080/profiles. В http-заголовках обязательно указываем Content-Type: application/json.
<
«firstName» : «Петр» ,
«lastName» : «Сидоров» ,
«age» : 14
>
В ответ в случае успеха получаем http-статус 201. Если же мы попытаемся нарушить наши ограничения по полям, то получим json с подробным описанием ошибки.
Таким образом, Spring Boot позволяет буквально за 5 минут создать полноценный обработчик POST-запроса с валидацией входящих параметров.
В следующей статье Обновление записи через PUT-запрос в Spring Boot рассмотрим как можно обновлять записи.
Postmapping spring как работает

Архитектура современных приложений состоит из отдельных модулей, как показано на рисунке выше. Эти модули часто называют Frontend и Backend. Frontend – это модуль, который отвечает за юзер-интерфейс и логику, которые предоставляется приложением при использовании. Так, например когда мы заходим в соцсети через браузер, мы взаимодействуем именно с FrontEnd-модулем приложения. То, как отображаются наши посты в виде сторисов или карточек, сообщения и другие активности реализуются именно в FrontEnd-модуле. А все данные, которые мы видим, хранятся и обрабатываются в Backend или серверной части приложения. Эти модули обмениваются между собой посредством разных архитектурных стилей: REST, GRPC и форматов сообщений – JSON и XML.
В этой статье мы напишем примитивную серверную часть социальной сети с использованием Spring Boot, запустим свой сервер, рассмотрим разные типы HTTP запросов и их применение.
Необходимое требование к читателю: умение писать на Java и базовые знания Spring Framework. Данная статья познакомит вас со Spring Boot и даст базовые понятия данного фреймворка.
☕ Подтянуть свои знания по Java вы можете на нашем телеграм-канале «Библиотека Java для собеса»
Инициализация проекта
Чтобы создать Spring Boot проект, перейдем на страницу https://start.spring.io/ и выберем необходимые зависимости: в нашем случае Spring Web. Чтобы запустить проект, необходима минимальная версия Java 17. Скачиваем проект и открываем в любом IDE (в моем случае – Intellij Idea)

Spring Web – зависимость, которая предоставляет контейнер сервлетов Apache Tomcat (является дефолтным веб-сервером). Проще говоря, сервлеты – это классы, которые обрабатывают все входящие запросы.
Открываем проект и запускаем.

Мы видим, что проект запустился и готов обрабатывать запросы на порту 8080 – Tomcat started on port(s): 8080 (http) .
Теперь создадим свой первый класс – GreetingController . Controller-классы ответственны за обработку входящих запросов и возвращают ответ.
Чтобы сделать наш класс Controller , достаточно прописать аннотацию @RestController . @RequestMapping указывает, по какому пути будет находиться определённый ресурс или выполняться логика.

Если отправить запрос по адресу http://localhost:8080/ , мы получим ошибку, т. к. по этому пути не определены логика обработки запроса и ресурсы.
☕ Интересные задачи по Java для практики можно найти на нашем телеграм-канале «Библиотека задач по Java»
Request Params
При отправке запросов мы часто используем переменные в запросе, чтобы передавать дополнительную информацию или же делать запросы гибкими. Параметр в запросе передаётся в конце адреса ( =url ) сервера и указывается после вопросительного знака ( =? ).
Например, http://localhost:8080/greet?name=Alice . Параметр запроса является = name cо значением = Alice .
Чтобы обрабатывать переменную запроса, используется аннотация @RequestParam . Параметры запроса могут быть опциональными или же обязательными. @RequestParam(«name») означает следующее: взять ту переменную из запроса, название которого равно name .

Вдобавок, запрос может содержать несколько параметров.
Например, http://localhost:8080/greet/full?name=John&surname=Smith . Параметры выделяются знаком & . В этом запросе два параметра: name=John и surname=Smith .
Чтобы обработать каждый параметр запроса, нужно пометить каждую переменную @RequestParam .

Path Variable
PathVariable по применению похож на @Request Param . @PathVariable также является параметром запроса, но используются внутри адреса запроса. Например,
RequestParam – http://localhost:8080/greet/full?name=John&surname=Smith
PathVariable – http://localhost:8080/greet/John . В этом случае John является PathVariable.
В запросе можно указывать несколько PathVariable, как и в случае RequestParam

Запрос с двумя параметризованными PathVariable.

HTTP-методы
Когда мы говорим о запросах, мы также подразумеваем HTTP-метод, который используется при отправке этого запроса. Каждый запрос представляет собой некий HTTP-метод. Например, когда мы переходим в браузере по адресу http://localhost:8080/greet/John/Smith , наш браузер отправляет GET-запрос на сервер.
Большая часть информационных систем обмениваются данными посредством HTTP-методов. Основными HTTP-методами являются – POST , GET , PUT , DELETE . Эти четыре запроса также называют CRUD-запросами.
- POST-метод – используется при создании новых ресурсов или данных. Например, когда мы загружаем новые посты в соцсетях, чаще всего используется POST-запросы. POST-запрос может иметь тело запроса.
- GET-метод – используется при получении данных. Например, при открытии любого веб-приложения, отправляется именно GET-запрос для получения данных и отображения их на странице. GET-запрос не имеет тела запроса.
- PUT-метод – используется для обновления данных, а также может иметь тело запроса, как и POST.
- DELETE-метод – используется для удаления данных.
Реализация основных методов
Давайте создадим сущности и реализуем методы, чтобы наш сервер принимал все четыре запроса. Для этого создадим сущности User и Post , и будем проводить операции над ними.
Для простоты User имеет только два поля: username и список постов posts , а сущность Post имеет поле description и imageUrl .

GET-запрос: получение пользователей

PUT-запрос: обновление списка постов пользователя

DELETE-запрос: удаление пользователя по username

В этой статье мы рассмотрели архитектуру современных web-приложений, а также написали свою серверную часть приложения, получив поверхностные знания по Spring Boot , HTTP запросы и параметры запросов.
Ссылка на репозиторий
Исходный код можно найти по ссылке.
Материалы по теме
- ☕ Сертификаты и тренинги для Java-разработчика
- ☕️ Дорожная карта Java-разработчика в 2023 году: путь с нуля до первой работы
Http метод (POST) @RequestMapping или @PostMapping?
Какие различия у этих 2 методов?
UPD.
Какой из этих вариантов нужно использовать в плане поддержки и правильности кода?
Отслеживать
Петровченко Иван
задан 30 янв 2019 в 8:47
Петровченко Иван Петровченко Иван
1,913 1 1 золотой знак 13 13 серебряных знаков 36 36 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Различий — никаких, просто для удобства добавили @PostMapping .
Если откроете исходники, то увидите следующее:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented @RequestMapping(method = RequestMethod.POST) public @interface PostMapping < /** * Alias for . */ @AliasFor(annotation = RequestMapping.class) String name() default ""; . >
Некоторые статические анализаторы кода, типа Sonar, могут ругаться на использование RequestMapping
Используйте @PostMapping и будет Вам счастье (но это не точно:))