Главная » Spring » Альтернативы JSP1

0

В октябре 1908 года Генри Форд (Henry Ford) выпустил «авто- мобиль для широких масс»: Форд Модель-Т (Model-T Ford). Пре- йскурантная цена составила $950. Чтобы ускорить сборку, все ав- томобили серии «Модель-Т» красились в черный цвет, потому что черная краска сохла быстрее остальных. Легенда приписывает Генри Форду слова: «Вы можете купить у меня автомобиль любого цвета, при условии что этот цвет будет черным».

С тех пор автомобили проделали длинный путь в своем развитии. В дополнение к головокружительному разнообразию форм кузова у нас появилась также возможность выбирать модель радиоприемни- ка/CD-проигрывателя, заказывать установку электрических стекло- подъемников и замков на двери, а также матерчатую или кожаную обивку салона. И в наше время любой может купить автомобиль любого цвета, включая черный.

До настоящего момента мы использовали технологию JSP при создании представлений для приложения. Но, в отличие от черной краски Генри Форда, JSP – не единственная технология создания представлений, доступная для выбора. Двумя другими популярны- ми механизмами шаблонов являются Velocity и FreeMarker. Посмот- рим, как использовать эти механизмы вместе с фреймворком Spring MVC.

Использование шаблонов Velocity

Velocity – простой в использовании язык шаблонов для прило- жений на Java. Шаблоны Velocity не содержат программного кода на Java, что облегчает их понимание не только разработчиками, но и неразработчиками. Цитата из руководства пользователя Velocity:

«Velocity отделяет код Java от веб-страниц, делая веб-сайт более простым для длительного сопровождения и обеспечивая жизнеспо- собную альтернативу технологии JavaServer Pages».

1 Этот и следующий разделы взяты из предыдущей редакции книги, охва- тывающей Spring 2. В связи с этим хотелось бы отметить следующее: не- смотря на то что в SpringSource стараются поддерживать обратную совмес- тимость между версиями продукта, есть небольшой риск, что конкретно этот функционал может работать несколько иначе в версии Spring 3. Поэтому информация в этих разделах актуальна для версии Spring 2. – Прим. ред.

После JSP Velocity – вероятно, самый популярный язык шабло- нов для веб-приложений на основе Java. Поэтому вполне возмож- но, что у вас появится желание разработать Spring-приложение с использованием Velocity в качестве технологии реализации уровня представлений. К счастью, Spring поддерживает Velocity как язык шаблонов уровня представлений для Spring MVC.

Посмотрим, как использовать Velocity со Spring MVC, реализовав уровень представлений приложения RoadRantz на основе Velocity.

Определение представления средствами Velocity

Предположим, что в качестве технологии реализации уровня представлений вы решили использовать Velocity вместо JSP. Выше уже был представлен пример реализации домашней JSP-страницы. А теперь посмотрим на шаблон Velocity – home.vm (листинг 8.15), используемый для отображения домашней страницы.

Листинг 8.15. Реализация домашней страницы на основе Velocity

<html>

<head><title>Rantz</title></head>

<body>

<h2>Rantz:</h2>

<a   href="addRant.htm">Add   rant</a><br/>

<a   href="register.htm">Register   new   motorist</a><br/>

<ul>

#foreach($rant  in  $rants)                    <!–  Итерации  по  элементам  списка  –>

<li> ${rant.vehicle.state}/

${rant.vehicle.plateNumber}  –

${rant.rantText}</li>

#end

</ul>

</body>

</html>

Шаблоны Velocity и JSP имеют не так много отличий. Но есть одно, сразу бросающееся в глаза, – отсутствие тегов шаблона. Это обусловлено тем, что механизм Velocity не опирается на использо- вание тегов, как JSP. Вместо этого используется собственный язык, известный как Velocity Template Language (VTL), содержащий ин- струкции управления потоком выполнения и другие директивы.

Директива #foreach в файле home.vm используется для организации цикла по списку элементов, отображая в каждой итерации свойства очередного элемента.

Несмотря на это отличие, выражения языка Velocity во многом напоминают язык JSP. Фактически JSP просто следовал по пятам за Velocity, используя нотацию ${} в выражениях своего собственного языка.

Приведенный пример шаблона демонстрирует лишь малую толи- ку возможностей Velocity. Чтобы узнать больше, посетите домаш- нюю страницу проекта Velocity по адресу: http://jakarta.apache.org/ velocity.

Теперь, после создания шаблона, необходимо настроить Spring на использование шаблонов Velocity в качестве представления в при- ложении на основе Spring MVC.

Настройка механизма Velocity

В первую очередь следует настроить сам механизм Velocity. Для этого нужно объявить компонент VelocityConfigurer в файле конфи- гурации Spring, как показано ниже:

<bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.

➥  VelocityConfigurer">

<property name="resourceLoaderPath" value="WEB-INF/velocity/" />

</bean>

Компонент VelocityConfigurer отвечает за настройку  механизма Velocity в Spring. Свойство resourceLoaderPath определяет место по- иска шаблонов. Я рекомендую помещать шаблоны в каталог, нахо- дящийся внутри каталога WEB-INF, чтобы к шаблонам нельзя было обратиться непосредственно.

Знакомые с Velocity уже знают, что настройки поведения Velocity можно определять в файле velocity.properties. Однако те же самые настройки можно определить с помощью VelocityConfigurer, в свой- стве velocityProperties. Например, взгляните на следующее объявле- ние компонента VelocityConfigurer:

<bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.

➥  VelocityConfigurer">

<property name="resourceLoaderPath" value="WEB-INF/velocity/" />

<property name="velocityProperties">

<props>

<prop    key="directive.foreach.counter.name">loopCounter</prop>

<prop     key="directive.foreach.counter.initial.value">0</prop>

</props>

</property>

</bean>

Здесь мы настроили механизм Velocity и изменили поведение цикла #foreach. По умолчанию цикл #foreach поддерживает перемен- ную-счетчик с именем $velocityCount, которая получает значение 1 в первой итерации цикла. Здесь мы присвоили свойству directive. foreach.counter.name значение loopCounter, чтобы к счетчику цикла можно было обращаться по имени $loopCounter. Кроме того, мы опре- делили начальное значение счетчика цикла, присвоив значение 0 свойству directive.foreach.counter.initial.value. (Более подробную информацию о конфигурационных свойствах Velocity можно полу- чить в руководстве разработчика по адресу: http://jakarta.apache. org/velocity/developer-guide.html).

Разрешение представлений Velocity

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

<bean id="viewResolver" class="org.springframework.web.servlet.view.

➥  velocity.VelocityViewResolver">

<property  name="suffix"  value=".vm"  />

</bean>

Компонент VelocityViewResolver для Velocity – почти то же самое, что InternalResourceViewResolver для JSP. Как и InternalResourceViewResolver, он имеет свойства prefix и suffix, которые вместе с логическим име- нем представления используются для формирования пути к шабло- ну. В данном случае достаточно установить только свойство suffix, указав в нем расширение .vm. Префикс не требуется, потому что путь к каталогу шаблонов уже был указан в свойстве resourceLoaderPath компонента VelocityConfigurer.

Примечание. Здесь атрибуту id компонента присвоено значение viewResolver. Это обстоятельство играет важную роль, когда сервлет DispatcherServlet не настроен на поиск всех арбитров представлений. Ес- ли в приложении придется использовать несколько арбитров представ- лений, то, вероятно, придется изменить значение атрибута id на что-то более подходящее (и уникальное), такое как velocityViewResolver.

Теперь приложение готово отображать представления, основан- ные на шаблонах Velocity. Для этого достаточно просто вернуть объ- ект ModelAndView, ссылающийся на представление по его логическому имени. В случае с HomeController делать вообще ничего не потребует- ся, потому что он уже возвращает объект ModelAndView:

return  new  ModelAndView("home",  "rants",  recentRants);

Представление имеет логическое имя home. Когда имя представле- ния будет определено, к home будет прибавлено расширение .vm, что- бы сконструировать имя файла шаблона home.vm. Компонент Velocity- ViewResolver найдет этот шаблон в пути WEB-INF/velocity/.

Что касается объекта модели rants, то он будет доступен в шабло- не в виде свойства Velocity. В листинге 8.15 этот объект представляет коллекцию, по которой директива #foreach выполняет итерации.

Форматирование дат и чисел

Несмотря на то что приложение уже готово отображать представ- ления Velocity, осталось еще несколько нерешенных вопросов. Если внимательно изучить шаблон home.vm (листинг 8.15), можно заме- тить, что в home.vm отсутствует форматирование дат, поэтому было бы желательно настроить некоторые параметры и тем самым обе- спечить надлежащее форматирование даты.

Язык VTL не поддерживает форматирование дат непосредствен- но. Однако в Velocity имеются инструменты для форматирования дат и чисел. Чтобы сделать их доступными, необходимо сообщить арбитру VelocityViewResolver названия атрибутов, посредством кото- рых эти инструменты будут экспортироваться. Имена атрибутов определяются через свойства dateToolAttribute и numberToolAttribute компонента VelocityViewResolver:

<bean id="viewResolver" class="org.springframework.web.servlet.view.

➥  velocity.VelocityViewResolver">

<property  name="suffix"  value=".vm"  />

<property  name="dateToolAttribute">

<value>dateTool</value>

</property>

<property name="numberToolAttribute">

<value>numberTool</value>

</property>

</bean>

Здесь указывается, что инструмент форматирования дат будет доступен в шаблоне под именем $dateTool. То есть, чтобы отформа- тировать дату, достаточно передать ее функции format инструмента. Например:

$dateTool.format("FULL", rant.postedDate)

Первый параметр – строка шаблона. Здесь используется тот же синтаксис, что и в java.text.SimpleDateFormat. Кроме того, можно указать один из стандартных шаблонов java.text.DateFormat, передав в виде строки шаблона одно из значений: FULL, LONG, MEDIUM, SHORT или DEFAULT. Здесь использовано значение FULL, соответствующее формату представления полной даты.

Как уже упоминалось, атрибут $numberTool представляет в шаблоне Velocity инструмент для форматирования чисел. За более подробной информацией об этом инструменте и об инструменте форматирова- ния дат обращайтесь к документации Velocity.

Экспортирование атрибутов запроса и сеанса

Большинство данных, которые должны быть отображены в шаб- лоне Velocity, можно передать представлению через объект Map, ко- торый передается объекту ModelAndView, однако иногда может потре- боваться вывести значения атрибутов таких объектов сервлета, как запрос или сеанс. Например, если пользователь зарегистрировался в приложении, в объекте сеанса сервлета может содержаться инфор- мация о пользователе.

Было бы очень неудобно, если бы мы были вынуждены копи- ровать атрибуты из запроса или сеанса в данные модели в каж- дом контроллере. К счастью, VelocityViewResolver может копировать атрибуты в модель автоматически. Свойства exposeRequestAttributes и  exposeSessionAttributes  сообщают  компоненту  VelocityViewResolver о необходимости копирования атрибутов запроса и сеанса в модель данных. Например:

<bean id="viewResolver" class="org.springframework.

➥    web.servlet.view.velocity.VelocityViewResolver">

<property  name="exposeRequestAttributes">

<value>true</value>

</property>

<property  name="exposeSessionAttributes">

<value>true</value>

</property>

</bean>

По умолчанию оба эти свойства имеют значение false. Но здесь мы установили их в значение true, так как нам необходимо, чтобы атрибуты запроса и сеанса были скопированы в модель данных и были доступны в шаблоне Velocity.

Связывание полей форм в шаблонах Velocity

Ранее в этой главе было показано, как с помощью библиотеки тегов JSP в Spring связывать поля форм со свойствами объектов и отображать сообщения об ошибках. Хотя в Velocity нет тегов, тем не менее Spring обеспечивает ряд макроопределений Velocity, предо- ставляющих возможности, эквивалентные библиотекам тегов JSP. В табл. 8.2 перечислены макроопределения Velocity, поставляемые в составе Spring.

Большая часть макроопределений в табл. 8.2 предназначена для связывания полей форм. То есть они генерируют элементы HTML- форм, значения которых связаны со свойствам объектов. Конкретное свойство объекта для связывания определяется в первом параметре (с именем path в таблице). Большинство макроопределений имеют параметр, позволяющий определять дополнительные атрибуты для генерируемых HTML-элементов (например, length="20").

Таблица 8.2. Spring MVC предоставляет коллекцию макроопреде- лений Velocity для связывания полей форм с объектом

Макроопределение

Назначение

#springFormCheckboxes(path options  separator  attributes)

Отображает набор флажков. Устанавливает состояние флажков согласно значениям свойств объекта

#springFormHiddenInput(path attributes)

Генерирует скрытое поле, связанное со свойством объекта

Таблица 8.2 (окончание)

Макроопределение

Назначение

#springFormInput(path attributes)

Отображает текстовое поле, связанное со свойством объекта

#springFormMultiSelect(path options   attributes)

Отображает список выбора, допускающий возможность выбора нескольких пунктов одновременно, связанный со свойством объекта

#springFormPasswordInput(path attributes)

Отображает поле ввода пароля, связанное со свойством объекта

#springFormRadioButtons(path options  separator  attributes)

Отображает набор радиокнопок, связанный со свойством объекта

#springFormSingleSelect(path options   attributes)

Отображает список выбора, допускающий возможность выбора единственного пункта, связанный со свойством объекта. Выбранное значение связано со свойством объекта

#springFormTextarea(path attributes)

Отображает текстовую область ввода, связанную со свойством объекта

#springMessage(messageCode)

Отображает «внешнее сообщение» из пакета ресурсов

#springMessageText(messageCode text)

Отображает «внешнее сообщение» из пакета ресурсов со значением по умолчанию, если сообщение не найдено в пакете ресурсов

#springShowErrors(separator class/style)

Отображает ошибки, выявленные при проверке

#springUrl(relativeUrl)

Отображает абсолютный URL по заданному относительному URL

Для демонстрации использования макроопределений Velocity в Spring рассмотрим еще раз представление addRant. В листинге 8.16 приводится содержимое файла addRant.vm – шаблона Velocity этого представления.

Листинг 8.16. Шаблон Velocity представления для добавления сообщений

<html>

<head>

<title>#springMessage("title.addRant")</title>

</head>

<body>

<h2>#springMessage("title.addRant")</h2>

<form   method="POST"   action="addRant.htm">

<b>#springMessage("field.state")</b>#springFormInput(

"rant.vehicle.state"  "")<br/>

<b>#springMessage("field.plateNumber")  </b>

#springFormInput("rant.vehicle.plateNumber" "")<br/>

#springMessage("field.rantText")

#springFormTextarea("rant.rantText" "rows=’5’ cols=’50’")

<input  type="submit"/>

</form>

</body>

</html>

Для организации ввода названия страны и регистрационного но- мера используются макроопределения #springFormInput, связывающие поля ввода со свойствами rant.vehicle.state и rant.vehicle.plateNumber соответственно. Это означает, что при получении формы, значения будут свойства state и plateNumber свойства vehicle управляющего объекта (rant). В обоих случаях нет необходимости определять до- полнительные атрибуты в разметке HTML, поэтому во втором пара- метре передается пустая строка. В результате получается следующая разметка HTML с полями:

<b>State:  </b><input  type="text"  id="vehicle.state" name="vehicle.state"  value=""  />  <br/>

<b>Plate #: </b><input type="text" id="vehicle.plateNumber" name="vehicle.plateNumber" value="" /> <br/>

Далее следует область ввода <textarea>, куда пользователь вводит текст сообщения. Область ввода отображается макроопределением

#springFormTextarea, которое связывает ее со свойством rant.rantText. То есть после получения формы текст будет сохранен в свойстве rantText управляющего объекта. В данном случае необходимо опре- делить размеры текстовой области, поэтому во втором параметре мы передаем дополнительные атрибуты. Разметка HTML текстовой области выглядит следующим образом:

<textarea id="rantText" name="rantText"

rows=’5′ cols=’50’></textarea>

Чтобы иметь возможность использовать в своих шаблонах мак- роопределения из фреймворка Spring, необходимо включить их под- держку в свойстве exposeSpringMacroHelpers компонента VelocityView- Resolver:

<bean id="viewResolver" class="org.springframework.web.servlet.view.

➥  velocity.VelocityViewResolver">

<property  name="suffix"  value=".vm"  />

<property name="exposeSpringMacroHelpers" value="true" />

</bean>

Установив свойство exposeSpringMacroHelpers в значение true, можно быть уверенными, что ваши шаблоны получат доступ к макроопре- делениям для Velocity, имеющимся в фреймворке Spring.

Механизм шаблонов Velocity широко используется как альтерна- тива JSP, но выбор альтернатив на этом не ограничивается. Другим широко известным механизмом шаблонов является FreeMarker, спо- собный заменить JSP в приложениях на основе Spring MVC. Давай- те посмотрим, как включить поддержку FreeMarker в приложение на основе Spring MVC.

Источник:   Уоллс К., Spring в действии. – М.: ДМК Пресс, 2013. – 752 с.: ил.

По теме:

  • Комментарии