Теперь контроллеры Taco Cloud не только отображают и записывают входные данные, но и проверяют соответствие информации некоторым основным правилам проверки. Давайте вернемся назад и пересмотрим HomeController из главы 1, глядя на альтернативную реализацию.
2.4 Работа с контроллерами отображения
До сих пор вы написали три контроллера для приложения Taco Cloud. Хотя каждый контроллер служит определенной цели в функциональности приложения, все они в значительной степени следуют одной модели программирования:
Они все аннотированы @Controller, чтобы указать, что они классы контроллеры, которые должны автоматически обнаруживаться при сканировании компонентов Spring и создаваться как bean в контексте приложения Spring.
Все, кроме HomeController, аннотируются @RequestMapping на уровне класса, чтобы определить базовый шаблон запроса, который будет обрабатывать контроллер.
Все они имеют один или несколько методов, аннотированных @GetMapping или@PostMapping, чтобы предоставить сведения о том, какие методы должны обрабатывать какие типы запросов.
Большинство контроллеров, которые вы напишете, будут следовать этому шаблону. Но когда контроллер достаточно прост, что он не заполняет модель или процесс ввода-как в случае с вашим HomeController-есть еще один способ, которым вы можете определить контроллер. Посмотрите на следующий листинг, чтобы увидеть, как можно объявить контроллер представления - контроллер, который ничего не делает, но перенаправляет запрос к представлению.
Листинг 2.15 Объявление контроллера отображения
package tacos.web;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
}
Самое важное о WebConfig, то что он реализует интерфейс WebMvcConfigurer. WebMvcConfigurer определяет несколько методов для настройки Spring MVC. Несмотря на то, что это интерфейс, он обеспечивает реализацию всех методов по умолчанию, поэтому вам нужно переопределить только необходимые методы. В этом листинге переопределен метод addViewControllers().
Метод addViewControllers() получает ViewControllerRegistry, который можно использовать для регистрации одного или нескольких контроллеров представления. Здесь вы вызываете addViewController() в реестре, передавая "/", путь, по которому ваш контроллер представлений будет обрабатывать запросы GET. Этот метод возвращает объект регистрации контроллера представлений, на котором вы немедленно вызываете setViewName(), чтобы указать home в качестве представления, на которое должен быть перенаправлен запрос "/".
И вот так просто, вы смогли заменить HomeController несколькими строками в классе конфигурации. Теперь вы можете удалить HomeController, и приложение должно вести себя так же, как и раньше. Единственное другое изменение, необходимое для пересмотра HomeControllerTest из главы 1, удаление ссылки на HomeController из аннотации @WebMvcTest, так чтобы тестовый класс будет компилироваться без ошибок.
Здесь вы создали новый класс конфигурации WebConfig для размещения объявления контроллера представления. Но любой класс конфигурации может реализовать WebMvcConfigurer и переопределить метод addViewController. Например, вы могли бы добавить такое же объявление контроллера представления в начальный класс приложения Taco Cloud, например так:
@SpringBootApplication
public class TacoCloudApplication implements WebMvcConfigurer {
public static void main(String[] args) {
SpringApplication.run(TacoCloudApplication.class, args);
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
}
Расширяя существующий класс конфигурации, можно избежать создания нового класса конфигурации, сохраняя обратное взаимодействие артефактов проекта. Но я предпочитаю создавать новый класс конфигурации для каждого типа конфигурации (веб, данные, безопасность и т. д.), сохраняя конфигурацию начальной загрузки приложения чистой и простой.
Говоря о контроллерах представлений и более общих представлениях, на которые контроллеры перенаправляют запросы, до сих пор вы использовали Thymeleaf для всех своих представлений. Мне нравится Thymeleaf, но, может, вы предпочитаете другой шаблонизатор для отображения данных приложения. Давайте посмотрим на другие шаблонизаторы поддерживаемые Spring.
2.5 Выбор библиотеки шаблонов представлений
В большинстве случаев выбор библиотеки шаблонов представлений зависит от личных предпочтений. Spring очень гибка и поддерживает множество распространенных вариантов шаблонов. За некоторыми небольшими исключениями, библиотека шаблонов, которую вы выберете, сама не будет иметь представления о том, что она даже работает с Spring (одним из таких исключений является -Spring Security dialect Thymeleaf, о котором мы поговорим в главе 4).
Таблица 2.2 Каталог опции шаблона, поддерживаемые автоконфигурацией Spring Boot.
Шаблоны
Spring Boot starter зависимости
FreeMarker
spring-boot-starter-freemarker
Groovy Templates
spring-boot-starter-groovy-templates
JavaServer Pages (JSP)
Нет (предоставлено Tomcat или Jetty)
Mustache
spring-boot-starter-mustache
Thymeleaf
spring-boot-starter-thymeleaf
Вообще говоря, вы выбираете нужную библиотеку шаблонов представления, добавляете ее в качестве зависимости в сборку и начинаете писать шаблоны в каталоге /templates (в каталоге src/main/resources в проекте, построенном на Maven или Gradle). Spring Boot обнаружит выбранную библиотеку шаблонов и автоматически настроит компоненты, необходимые для обслуживания представлений контроллеров Spring MVC.
Вы уже сделали это с Thymeleaf для приложения Taco Cloud. В главе 1 при инициализации проекта был установлен флажок Thymeleaf. Это привело к Spring Boot Thymeleaf starter-у в файле pom.xml. При запуске приложения автоконфигурация Spring Boot обнаруживает наличие Thymeleaf и автоматически настраивает bean-ы Thymeleaf для вас. Все, что вам нужно было сделать, это начать писать шаблоны в /templates.
Если вы предпочитаете использовать другую библиотеку шаблонов, просто выберите ее при инициализации проекта или отредактируйте существующую сборку проекта, чтобы включить новую выбранную библиотеку шаблонов.
Например, скажем, вы захотели использовать Mustache вместо Thymeleaf. Не проблема. Просто откройте в проекте pom.xml-файл и замените объявление,
на:
Конечно, вам нужно будет убедиться, что вы пишете все шаблоны с синтаксисом Mustache вместо тегов Thymeleaf. Особенности работы с Mustache(или любой из вариантов языка шаблона) выходят далеко за рамки этой книги, но чтобы дать вам представление о том, чего ожидать, вот фрагмент из шаблона Mustache, который будет отображать одну из групп ингредиентов в форме дизайна taco:
Designate your wrap:
{{#wrap}}
{{name}}
{{/wrap}}
Это Mustache эквивалент фрагмента Thymeleaf в разделе 2.1.3. Блок {{#wrap}} (который завершается {{/wrap}}) перебирает коллекцию в атрибуте запроса, ключом которого является wrap, и отображает встроенный HTML для каждого элемента. Теги {{{id}} и {{name}} ссылаются на свойства id и name элемента (который должен быть Ingredient).
Вы заметили в таблице 2.2, что JSP не требует каких-либо специальных зависимостей в сборке. Это потому, что сам контейнер сервлета (Tomcat по умолчанию) реализует спецификацию JSP, таким образом не требуя никаких дополнительных зависимостей.
Но есть проблема, если вы решите использовать JSP. Как оказалось, контейнеры сервлетов Java, включая встроенные контейнеры Tomcat и Jetty, обычно ищут JSP где—то в /WEB-INF. Но если вы создаете приложение в виде исполняемого файла JAR, нет способа удовлетворить это требование. Таким образом JSP является вариантом только, если вы создаете приложение в виде файла WAR и развертывания его в контейнере традиционного сервлета. При создании исполняемого файла JAR необходимо выбрать Thymeleaf, FreeMarker или один из других вариантов из таблицы 2.2.
2.5.1 Кэширование шаблонов
По умолчанию шаблоны анализируются только один раз при первом использовании и результаты этого анализа кэшируются для последующего использования. Это отличная функция для производительности, так как она предотвращает избыточный парсинг шаблонов по каждому запросу и, таким образом, повышает производительность.
Однако эта функция не так полезна во время разработки. Предположим, вы запускаете свое приложение и нажимаете страницу создания тако и решаете внести в нее несколько изменений. При обновлении веб-браузера вам все равно будет показана исходная версия. Единственный способ увидеть изменения-перезапустить приложение, что довольно неудобно.
К счастью, есть способ отключить кэширование. Все, что вам нужно сделать, это установить свойство кэширования, соответствующее шаблону, в false. В таблице 2.3 перечислены свойства кэширования для каждого из поддерживаемых библиотек шаблонов.