1. Обзор
Для конечного пользователя процесс отправки формы удобен и в некоторой степени эквивалентен простому вводу данных и нажатию на кнопку отправки. Однако с инженерной точки зрения требуется механизм кодирования, чтобы надежно отправлять и получать эти данные со стороны клиента на сторону сервера для внутренней обработки.
В рамках этого урока мы сосредоточимся на создании формы, которая отправляет свои данные в виде application | x-www-form-urlencoded |/content type в веб-приложении Spring.
2. Кодирование данных Формы
Наиболее часто используемым методом HTTP для отправки форм является POST. Однако для отправки идемпотентных форм мы также можем использовать метод HTTP GET. И способ указать метод-через атрибут метода формы/|.
Для форм, использующих метод GET, все данные формы отправляются как часть строки запроса. Но если мы используем метод POST, то его данные отправляются как часть тела HTTP-запроса.
Кроме того, в последнем случае мы также можем указать кодировку данных с помощью атрибута enctype формы , который может принимать два значения, а именно application/x-www-form-urlencoded | и multipart/form-data .
2.1. Тип носителя application/x-www-form-urlencoded
HTML формы имеют значение по умолчанию application/x-www-form-urlencoded для enctype атрибута , поскольку это учитывает основные случаи использования, когда данные являются полностью текстовыми. Тем не менее, если наш вариант использования включает поддержку данных файла, нам придется переопределить его значением multipart/form-data .
По сути, он отправляет данные формы в виде пар ключ-значение, разделенных символом амперсанда ( & ). Кроме того, соответствующий ключ и значение разделяются знаком равенства (=). Кроме того, все зарезервированные и не буквенно-цифровые символы кодируются с использованием процентного кодирования .
3. Отправка формы в браузере
Теперь, когда мы рассмотрели наши основы, давайте продолжим и посмотрим, как мы можем обрабатывать данные формы в кодировке URL для простого использования отправки обратной связи в веб-приложении Spring.
3.1. Модель предметной области
Для нашей формы обратной связи нам нужно записать идентификатор электронной почты отправителя вместе с комментарием. Итак, давайте создадим нашу модель домена в обратной связи классе :
public class Feedback {
private String emailId;
private String comment;
}3.2. Создать форму
Чтобы использовать простой HTML-шаблон для создания нашей динамической веб-формы, нам нужно настроить Thymeleaf в нашем проекте. После этого мы готовы добавить GETendpoint /feedback , который будет обслуживать feedback представление для формы :
@GetMapping(path = "/feedback")
public String getFeedbackForm(Model model) {
Feedback feedback = new Feedback();
model.addAttribute("feedback", feedback);
return "feedback";
}Обратите внимание, что мы используем feedback в качестве атрибута модели для захвата пользовательского ввода. Далее, давайте создадим обратную связь представление в feedback.html шаблон :
Конечно, нам не нужно явно указывать атрибут enctype , так как он выберет значение по умолчанию application/x-www-form-urlencoded .
3.3. Поток ПРГ
Поскольку мы принимаем вводимые пользователем данные через форму обратной связи браузера, мы должны реализовать рабочий процесс отправки POST/REDIRECT/GET (PRG), чтобы избежать дублирования отправлений .
Во-первых, давайте реализуем конечную точку POST /web/feedback , которая будет действовать в качестве обработчика действий для формы обратной связи:
@PostMapping(
path = "/web/feedback",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public String handleBrowserSubmissions(Feedback feedback) throws Exception {
// Save feedback data
return "redirect:/feedback/success";
}Затем мы можем реализовать конечную точку перенаправления /обратная связь/успех , которая обслуживает запрос GET:
@GetMapping("/feedback/success")
public ResponseEntity getSuccess() {
return new ResponseEntity("Thank you for submitting feedback.", HttpStatus.OK);
} Чтобы проверить функциональность рабочего процесса отправки формы в браузере, давайте посетим localhost:8080/обратная связь :
Наконец, мы также можем проверить, что данные формы отправляются в закодированной форме URL:
emailId=abc%40example.com&comment=Sample+Feedback
4. Запросы, не относящиеся к Браузеру
Иногда у нас может не быть HTTP-клиента на основе браузера. Вместо этого нашим клиентом может быть утилита, такая как cURL или Postman . В таком случае нам не нужна веб-форма HTML. Вместо этого мы можем реализовать конечную точку /feedback , которая обслуживает запрос POST:
@PostMapping(
path = "/feedback",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public ResponseEntity handleNonBrowserSubmissions(@RequestBody Feedback feedback) throws Exception {
// Save feedback data
return new ResponseEntity("Thank you for submitting feedback", HttpStatus.OK);
} В отсутствие HTML-формы в нашем потоке данных нам не обязательно реализовывать шаблон PRG. Однако мы должны указать, что ресурс принимает APPLICATION_FORM_URLENCODED_VALUE тип носителя .
Наконец, мы можем протестировать его с помощью запроса cURL:
curl -X POST \ http://localhost:8080/feedback \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'emailId=abc%40example.com&comment=Sample%20Feedback'
4.1. Основы FormHttpMessageConverter
HTTP-запрос, отправляющий application/x-www-form-urlencoded data, должен указывать это в заголовке Content-Type . Внутренне Spring использует класс FormHttpMessageConverter для чтения этих данных и связывания их с параметром метода.
В тех случаях , когда параметр нашего метода имеет тип MultiValueMap , мы можем использовать аннотацию @RequestParam или @RequestBody , чтобы соответствующим образом связать его с телом HTTP-запроса. Это связано с тем , что API сервлета объединяет параметры запроса и данные формы в единую карту, называемую parameters , и это включает автоматический анализ тела запроса:
@PostMapping(
path = "/feedback",
consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public ResponseEntity handleNonBrowserSubmissions(
@RequestParam MultiValueMap paramMap) throws Exception {
// Save feedback data
return new ResponseEntity("Thank you for submitting feedback", HttpStatus.OK);
} Однако для параметра метода типа, отличного от многозначной карты, такого как наш объект Обратная связь домен, мы должны использовать только аннотацию @RequestBody .
5. Заключение
В этом уроке мы кратко познакомились с кодированием данных форм в веб-формах. Мы также изучили, как обрабатывать данные, закодированные в URL-адресах, для HTTP-запросов браузера и не-браузера, реализовав форму обратной связи в веб-приложении Spring Boot.
Как всегда, полный исходный код учебника доступен на GitHub .