Spring in Action Covers Spring 5-1--11 — страница 8 из 63

Ваш DesignTacoController действительно начинает обретать форму. Если запустить приложение сейчас и указать в браузере путь /design, будет задействована функция showDesignForm() DesignTacoController, извлекающая данные из репозитория и помещающая их в модель перед передачей запроса в представление. Но поскольку вы еще не определили представление, запрос будет не корректен, что приведет к ошибке HTTP 404 (Not Found). Чтобы исправить это, давайте переключим наше внимание на представление, где данные будут представлены в виде HTML, которые будут отображаться в веб-браузере пользователя.

2.1.3 Проектирование представления

После того, как работы над контроллером закончены, пришло время для просмотра. Spring предлагает несколько отличных опций для определения представлений, включая JavaServer Pages (JSP), Thymeleaf, FreeMarker, Mustache и шаблоны на основе Groovy. На данный момент мы будем использовать Thymeleaf, выбор, который мы сделали в главе 1 при запуске проекта. Мы рассмотрим несколько других вариантов в разделе 2.5.

Чтобы использовать Thymeleaf, необходимо добавить еще одну зависимость в сборку проекта. Следующая запись добавит Thymeleaf в Spring Boot, чтобы сделать Thymeleaf доступным для рендеринга представления, которое вы собираетесь создать:


org.springframework.boot


spring-boot-starter-thymeleaf


Во время выполнения Spring Boot autoconfiguration увидит, что Thymeleaf находится в classpath и автоматически создаст bean, которые поддерживают представления Thymeleaf для Spring MVC.

Визуальные библиотеки, такие как Thymeleaf предназначены для отделения от определенного web  framework. Таким образом, они не знают об абстракции модели Spring и не могут работать с данными, которые контроллер помещает в Model. Но они могут работать с атрибутами запроса сервлета. Поэтому, прежде чем Spring передаст запрос представлению, он копирует данные модели в атрибуты запроса, к которым Thymeleaf и другие визуальные шаблонизаторы представлений имеют доступ.

Шаблоны Thymeleaf - это просто HTML с некоторыми дополнительными атрибутами элементов, которые корректируют шаблон при отображении данных запроса. Например, если бы существовал атрибут запроса, ключом которого является "message", и вы хотели, чтобы он отображался в теге HTML

с помощью Thymeleaf, вы бы написали следующее в шаблоне Thymeleaf:

placeholder message

При отображении шаблона в HTML тело элемента

будет заменено значением атрибута запроса сервлета, ключом которого является"message". Атрибут th:text является атрибутом пространства имен Thymeleaf, который выполняет замену. Оператор ${} указывает ему использовать значение атрибута запроса (в данном случае" message").

Thymeleaf также предлагает другой атрибут, th: each, который перебирает коллекцию элементов, добавляя HTML код для каждого элемента в коллекции. Это пригодится, когда вы создадите отображение, чтобы перечислить ингредиенты taco из модели. Например, чтобы отобразить только список ингредиентов "wrap", можно использовать следующий фрагмент HTML:

Designate your wrap:




INGREDIENT


Здесь используется атрибут th: each тега

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

Внутри элемента

есть элемент checkbox и элемент , чтобы предоставить метку для флажка. Флажок использует Thymeleaf th:value, чтобы задать для элемента значение атрибута value, найденное в свойстве ID компонента. Элемент использует th:text для замены текста-заполнителя "INGREDIENT" значением свойства name ингредиента.

При визуализации с фактическими данными модели одна итерация цикла

может выглядеть следующим образом:



Flour Tortilla


В конечном счете, предыдущий фрагмент Thymeleaf является лишь частью более крупной HTML-формы, через которую ваши творцы тако представят свои вкусные творения.  Полный шаблон Thymeleaf, включая все типы ингредиентов и форму, показан в следующем списке.

Листинг 2.3 Полный вид страницы дизайна тако



 xmlns:th="http://www.thymeleaf.org">



Taco Cloud





Design your taco!






Designate your wrap:




INGREDIENT





Pick your protein:




INGREDIENT





Choose your cheese:




INGREDIENT





Determine your veggies:




INGREDIENT





Select your sauce:




INGREDIENT






Name your taco creation:









Как вы можете видеть, вы повторяете фрагмент

для каждого из типов ингредиентов. И вы включаете кнопку отправки и поле, где пользователь может назвать свое тако-творение.

Также стоит отметить, что полный шаблон включает в себя изображение логотипа Taco Cloud и ссылку на таблицу стилей(Содержание таблицы стилей не имеет отношения к нашему обсуждению; она содержит только стиль, чтобы представить ингредиенты в двух столбцах вместо одного длинного списка ингредиентов) в обоих случаях оператор @{} используется для создания относительного к контексту пути к статическим артефактам, на которые они ссылаются. Как вы узнали из главы 1, статическое содержимое в приложении Spring Boot подается из каталога /static в корне пути к классам.

Теперь, когда ваш контроллер и визуальная часть полностью готовы, вы можете запустить приложение, чтобы увидеть плоды вашего труда. Существует множество способов запуска приложения Spring Boot. В главе 1 я показал вам, как запустить приложение, сначала создав его в исполняемый файл JAR, а затем запустив JAR с java-jar. Я также показал, как запустить приложение непосредственно из сборки с помощью mvn spring-boot:run.

Независимо от того, как вы запустите приложение Taco Cloud, как только оно запустится, укажите браузеру http://localhost:8080/design. Вы должны увидеть страницу, которая выглядит примерно как на рисунке 2.2.


Рисунок 2.2 Страница тако-создания

Это выглядит замечательно! Творцам тако, посетившим ваш сайт, предоставляется форма, содержащая палитру ингредиентов тако, из которых они могут создать свой шедевр. Но что происходит, когда они нажимают кнопку Submit Your Taco?

Ваш DesignTacoController еще не готов принять созданный тако. Если форма дизайна отправлена, пользователю будет представлена ошибка. (В частности, это будет ошибка HTTP 405: метод запроса "POST" не поддерживается.) Давайте исправим это, написав еще один код контроллера, который обрабатывает отправку формы.

2.2 Обработка отправки формы

Если еще раз взглянуть на тег

в представлении, можно увидеть, что его атрибут method имеет значение POST. Кроме того, не объявляет атрибут action. Это означает, что когда форма будет отправлена, браузер соберет все данные в форме и отправит ее на сервер в запросе HTTP POST к тому же пути, для которого запрос GET отобразил форму—путь /design.

Таким образом необходим метод обработчика контроллера на принимающей стороне запроса POST. Вам нужно написать новый метод обработчика в контроллере дизайна тако, который обрабатывает запрос POST для /design.

В листинге 2.2 вы использовали аннотацию @GetMapping, чтобы указать, что метод showDesignForm() должен обрабатывать запросы HTTP GET для /design. Также как @GetMapping обрабатывает GET-запросы, вы можете использовать @PostMapping для обработки POST-запросов. Для обработки созданных тако добавьте метод processDesign() как в следующем листинге для DesignTacoController.

Листинг 2.4 Обработка POST-запросов с @PostMapping