Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Модифицирующие формы Java: Веб-технологии

В этом уроке мы изучим формы, которые меняют данные. И с клиентской, и с серверной стороны они обычно устроены сложнее, чем поисковые формы. Для уверенной работы с ними нужно разбираться:

  • Как работают соответствующие HTML-теги
  • Как отправляются формы по HTTP
  • Как происходит обработка на стороне сервера
  • Как работает валидация и вывод ошибок

Все это мы изучим в ближайшее время.

Вывод формы

За вывод формы и ее обработку должны отвечать два разных маршрута — а значит, еще и два обработчика. Рассмотрим примеры маршрутов для создания нового пользователя:

  • GET /users/build — страница с формой, которую заполняет пользователь. Эта форма отправляет POST-запрос на адрес /users, указанный в атрибуте action
  • POST /users — маршрут, обрабатывающий данные формы

Для нашей задачи мы будем использовать класс пользователя. Он может выглядеть так:

@Getter
@Setter
public final class User {
    private Long id;

    private String name;
    private String email;
    private String password;

    public User(String name, String email, String password) {
        this.name = name;
        this.email = email;
        this.password = password;
    }
}

Добавим обработчик маршрута /users/build, который выводит форму добавления пользователя:

app.get("/users/build", ctx -> {
    ctx.render("users/build.jte");
});

Создадим форму в файле src/main/jte/users/build.jte:

<form action="/users" method="post">
  <div>
    <label>
      Имя
      <input type="text" name="name" />
    </label>
  </div>
  <div>
    <label>
      Email
      <input type="email" required name="email" />
    </label>
  </div>
  <div>
    <label>
      Пароль
      <input type="password" required name="password" />
    </label>
  </div>
  <div>
    <label>
      Подтверждение пароля
      <input type="password" required name="passwordConfirmation" />
    </label>
  </div>
  <input type="submit" value="Зарегистрировать" />
</form>

Запустим сервер и убедимся, что форма выводится по адресу /users/build. Если ее заполнить и попытаться отправить, то браузер сформирует следующий HTTP-запрос:

# Данные взяты для примера

POST /users HTTP/1.1
Host: localhost
Content-type: application/x-www-form-urlencoded
Content-length: 76

name=Mike&email=example@test.com&password=qwerty&passwordConfirmation=qwerty

В примере выше мы видели работу с HTTP, но на практике все устроено немного по-другому. Не стоит передавать электронную почту, пароль и другие чувствительные данные по обычному HTTP-протоколу, потому что так данные легко перехватить и использовать не по назначению.

Именно поэтому современные сайты обычно работают по протоколу HTTPS, который передает данные в зашифрованном виде.

Обработка данных

Форма готова, теперь можно реализовывать ее обработчик. Обработчик формы работает так:

  • Извлекает параметры формы через метод ctx.formParam()
  • Формирует объект пользователя на основе этих параметров
  • Сохраняет объект пользователя в базу данных
  • Выполняет редирект — например, на страницу пользователей

Код обработчика выглядит так:

app.post("/users", ctx -> {
    var name = ctx.formParam("name");
    var email = ctx.formParam("email");
    var password = ctx.formParam("password");
    var passwordConfirmation = ctx.formParam("passwordConfirmation");

    var user = new User(name, email, password);
    UserRepository.save(user);
    ctx.redirect("/users");
});

Примерно так выглядит большинство обработчиков форм. Они могут быть сложнее, но общая структура остается похожей: мы извлекаем данные, создаем нужные объекты на основе них и вносим изменения в базу. В конце мы выполняем редирект или формируем необходимый ответ клиенту.

Нормализация данных

Представим, что при регистрации пользователь написал свою почту в произвольном регистре — MYname@example.com вместо myname@example.com. По спецификации, адреса электронной почты не зависят от регистра. Другими словами, если в двух адресах совпадают буквы, то они считаются одним и тем же адресом.

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

  • Пользователь сможет зарегистрировать несколько аккаунтов на один и тот же адрес почты, просто вводя адрес в разном регистре
  • Пользователь не сможет зайти на сайт, если введет почту не в том регистре, который использовал при регистрации

Чтобы этого не происходило, введенные пользователями данные проходят нормализацию. В случае почты мы приводим ее к нижнему регистру:

// Это касается только адреса электронной почты
var name = ctx.formParam("name");
var email = ctx.formParam("email").toLowerCase();
var password = ctx.formParam("password");

Пользователь может не только ошибиться в регистре, но и случайно поставить пробелы в конце или в начале строк — например, из-за копирования. Иногда мы не можем на это влиять. Например, пользователь может специально добавить пробельный символ в начале и конце пароля.

А вот для имени и адреса почты такое недопустимо. Поэтому лучше обрезать концевые пробелы для надежности:

var name = ctx.formParam("name").trim();
var email = ctx.formParam("email").trim().toLowerCase();
var password = ctx.formParam("password");

Самостоятельная работа

  1. Выполните на своем компьютере все шаги из урока
  2. Добавьте в приложение форму и обработчики для добавления нового пользователя. Не забудьте сделать нормализацию электронной почты пользователя
  3. Измените код приложения так, чтобы пользователи в обработчиках подтягивались из репозитория
  4. Запустите приложение и попробуйте добавлять новых пользователей
  5. Проверьте, происходит ли редирект на страницу просмотра всех пользователей
  6. Проверьте, отображается ли новый пользователь в списке пользователей
  7. Сделайте то же самое для курсов
  8. Залейте изменения на GitHub

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка приложений на языке Java
10 месяцев
с нуля
Старт 2 мая

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»
Изображение Тото

Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу