HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>В этом уроке мы изучим формы, которые меняют данные. И с клиентской, и с серверной стороны они обычно устроены сложнее, чем поисковые формы. Для уверенной работы с ними нужно разбираться:</p>
1 <p>В этом уроке мы изучим формы, которые меняют данные. И с клиентской, и с серверной стороны они обычно устроены сложнее, чем поисковые формы. Для уверенной работы с ними нужно разбираться:</p>
2 <ul><li>Как работают соответствующие HTML-теги</li>
2 <ul><li>Как работают соответствующие HTML-теги</li>
3 <li>Как отправляются формы по HTTP</li>
3 <li>Как отправляются формы по HTTP</li>
4 <li>Как происходит обработка на стороне сервера</li>
4 <li>Как происходит обработка на стороне сервера</li>
5 <li>Как работает валидация и вывод ошибок</li>
5 <li>Как работает валидация и вывод ошибок</li>
6 </ul><p>Все это мы изучим в ближайшее время.</p>
6 </ul><p>Все это мы изучим в ближайшее время.</p>
7 <h2>Вывод формы</h2>
7 <h2>Вывод формы</h2>
8 <p>За вывод формы и ее обработку должны отвечать два разных маршрута - а значит, еще и два обработчика. Рассмотрим примеры маршрутов для создания нового пользователя:</p>
8 <p>За вывод формы и ее обработку должны отвечать два разных маршрута - а значит, еще и два обработчика. Рассмотрим примеры маршрутов для создания нового пользователя:</p>
9 <ul><li>GET<em>/users/build</em>- страница с формой, которую заполняет пользователь. Эта форма отправляет POST-запрос на адрес<em>/users</em>, указанный в атрибуте action</li>
9 <ul><li>GET<em>/users/build</em>- страница с формой, которую заполняет пользователь. Эта форма отправляет POST-запрос на адрес<em>/users</em>, указанный в атрибуте action</li>
10 <li>POST<em>/users</em>- маршрут, обрабатывающий данные формы</li>
10 <li>POST<em>/users</em>- маршрут, обрабатывающий данные формы</li>
11 </ul><p>Для нашей задачи мы будем использовать класс пользователя. Он может выглядеть так:</p>
11 </ul><p>Для нашей задачи мы будем использовать класс пользователя. Он может выглядеть так:</p>
12 <p>Добавим обработчик маршрута<em>/users/build</em>, который выводит форму добавления пользователя:</p>
12 <p>Добавим обработчик маршрута<em>/users/build</em>, который выводит форму добавления пользователя:</p>
13 <p>Создадим форму в файле<em>src/main/jte/users/build.jte</em>:</p>
13 <p>Создадим форму в файле<em>src/main/jte/users/build.jte</em>:</p>
14 <p>Запустим сервер и убедимся, что форма выводится по адресу<em>/users/build</em>. Если ее заполнить и попытаться отправить, то браузер сформирует следующий HTTP-запрос:</p>
14 <p>Запустим сервер и убедимся, что форма выводится по адресу<em>/users/build</em>. Если ее заполнить и попытаться отправить, то браузер сформирует следующий HTTP-запрос:</p>
15 <p>В примере выше мы видели работу с HTTP, но на практике все устроено немного по-другому. Не стоит передавать электронную почту, пароль и другие чувствительные данные по обычному HTTP-протоколу, потому что так данные легко перехватить и использовать не по назначению.</p>
15 <p>В примере выше мы видели работу с HTTP, но на практике все устроено немного по-другому. Не стоит передавать электронную почту, пароль и другие чувствительные данные по обычному HTTP-протоколу, потому что так данные легко перехватить и использовать не по назначению.</p>
16 <p>Именно поэтому современные сайты обычно работают по протоколу HTTPS, который передает данные в зашифрованном виде.</p>
16 <p>Именно поэтому современные сайты обычно работают по протоколу HTTPS, который передает данные в зашифрованном виде.</p>
17 <h2>Обработка данных</h2>
17 <h2>Обработка данных</h2>
18 <p>Форма готова, теперь можно реализовывать ее обработчик. Обработчик формы работает так:</p>
18 <p>Форма готова, теперь можно реализовывать ее обработчик. Обработчик формы работает так:</p>
19 <ul><li>Извлекает параметры формы через метод ctx.formParam()</li>
19 <ul><li>Извлекает параметры формы через метод ctx.formParam()</li>
20 <li>Формирует объект пользователя на основе этих параметров</li>
20 <li>Формирует объект пользователя на основе этих параметров</li>
21 <li>Сохраняет объект пользователя в базу данных</li>
21 <li>Сохраняет объект пользователя в базу данных</li>
22 <li>Выполняет редирект - например, на страницу пользователей</li>
22 <li>Выполняет редирект - например, на страницу пользователей</li>
23 </ul><p>Код обработчика выглядит так:</p>
23 </ul><p>Код обработчика выглядит так:</p>
24 <p>Примерно так выглядит большинство обработчиков форм. Они могут быть сложнее, но общая структура остается похожей: мы извлекаем данные, создаем нужные объекты на основе них и вносим изменения в базу. В конце мы выполняем редирект или формируем необходимый ответ клиенту.</p>
24 <p>Примерно так выглядит большинство обработчиков форм. Они могут быть сложнее, но общая структура остается похожей: мы извлекаем данные, создаем нужные объекты на основе них и вносим изменения в базу. В конце мы выполняем редирект или формируем необходимый ответ клиенту.</p>
25 <h2>Нормализация данных</h2>
25 <h2>Нормализация данных</h2>
26 <p>Представим, что при регистрации пользователь написал свою почту в произвольном регистре -<em><a>MYname@example.com</a></em>вместо<em><a>myname@example.com</a></em>. По спецификации, адреса электронной почты не зависят от регистра. Другими словами, если в двух адресах совпадают буквы, то они считаются одним и тем же адресом.</p>
26 <p>Представим, что при регистрации пользователь написал свою почту в произвольном регистре -<em><a>MYname@example.com</a></em>вместо<em><a>myname@example.com</a></em>. По спецификации, адреса электронной почты не зависят от регистра. Другими словами, если в двух адресах совпадают буквы, то они считаются одним и тем же адресом.</p>
27 <p>Проблема в том, что с точки зрения кода и большинства баз данных мы сравниваем строки с учетом регистра. В итоге наш проект ждут два сюрприза:</p>
27 <p>Проблема в том, что с точки зрения кода и большинства баз данных мы сравниваем строки с учетом регистра. В итоге наш проект ждут два сюрприза:</p>
28 <ul><li>Пользователь сможет зарегистрировать несколько аккаунтов на один и тот же адрес почты, просто вводя адрес в разном регистре</li>
28 <ul><li>Пользователь сможет зарегистрировать несколько аккаунтов на один и тот же адрес почты, просто вводя адрес в разном регистре</li>
29 <li>Пользователь не сможет зайти на сайт, если введет почту не в том регистре, который использовал при регистрации</li>
29 <li>Пользователь не сможет зайти на сайт, если введет почту не в том регистре, который использовал при регистрации</li>
30 </ul><p>Чтобы этого не происходило, введенные пользователями данные проходят<strong>нормализацию</strong>. В случае почты мы приводим ее к нижнему регистру:</p>
30 </ul><p>Чтобы этого не происходило, введенные пользователями данные проходят<strong>нормализацию</strong>. В случае почты мы приводим ее к нижнему регистру:</p>
31 <p>Пользователь может не только ошибиться в регистре, но и случайно поставить пробелы в конце или в начале строк - например, из-за копирования. Иногда мы не можем на это влиять. Например, пользователь может специально добавить пробельный символ в начале и конце пароля.</p>
31 <p>Пользователь может не только ошибиться в регистре, но и случайно поставить пробелы в конце или в начале строк - например, из-за копирования. Иногда мы не можем на это влиять. Например, пользователь может специально добавить пробельный символ в начале и конце пароля.</p>
32 <p>А вот для имени и адреса почты такое недопустимо. Поэтому лучше обрезать концевые пробелы для надежности:</p>
32 <p>А вот для имени и адреса почты такое недопустимо. Поэтому лучше обрезать концевые пробелы для надежности:</p>
33  
33