Apache FreeMarker — це шаблонізатор для генерації будь-якого виду текстового виведення від HTML до електронної пошти тощо. Spring Framework має вбудовану інтеграцію для використання Spring MVC з шаблонами FreeMarker.
Конфігурація подання
У наступному прикладі показано, як налаштувати FreeMarker як технологію подання:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker();
}
// Конфігуруємо FreeMarker...
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("/WEB-INF/freemarker");
return configurer;
}
}
@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.freeMarker()
}
// Конфігуруємо FreeMarker...
@Bean
fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
setTemplateLoaderPath("/WEB-INF/freemarker")
}
}
У наступному прикладі показано, як налаштувати те саме на XML:
<mvc:annotation-driven/>
<mvc:view-resolvers>
<mvc:freemarker/>
</mvc:view-resolvers>
<!-- Configuring FreeMarker... -->
<mvc:freemarker-configurer>
<mvc:template-loader-path location="/WEB-INF/freemarker"/>
</mvc:freemarker-configurer>
До того ж, можна оголосити бін FreeMarkerConfigurer
для повного контролю над усіма властивостями,
як показано в наступному прикладі:
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
</bean>
Твої шаблони повинні зберігатися в директорії, вказаній FreeMarkerConfigurer
, як показано в
попередньому прикладі. Враховуючи попередню конфігурацію, якщо твій контролер повертає ім'я подання
welcome
, перетворювач шукає шаблон /WEB-INF/freemarker/welcome.ftl
.
Конфігурація FreeMarker
Можна передати "Settings" і "SharedVariable" обробника FreeMarker безпосередньо до
об'єкта Конфігурація
обробника FreeMarker (який керується Spring), встановивши відповідні властивості
біна в FreeMarkerConfigurer
. Для якості freemarkerSettings
потрібен об'єкт java.util.Properties
,
а для якості freemarkerVariables
— java.util.Map
. У цьому прикладі показано, як
використовувати FreeMarkerConfigurer
:
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
<property name="freemarkerVariables">
<map>
<entry key="xml_escape" value-ref="fmXmlEscape"/>
</map>
</property>
</bean>
<bean id="fmXmlEscape" class="freemarker.template.utility.XmlEscape"/>
Подробиці про налаштування та змінні, які застосовуються до об'єкта Конфігурація
, див. у
документації FreeMarker.
Обробка форм
Spring передбачає бібліотеку тегів для використання в JSP, яка містить, серед іншого, елемент <spring:bind/>
.
Цей елемент насамперед дозволяє формам виводити на екран значення з базових об'єктів форми та відображати
результати невдалих перевірок з Validator
на вебрівні або бізнес-рівні. Spring також має підтримку
тієї ж функціональності FreeMarker, з додатковими зручними макросами для генерації самих елементів введення
форми.
Макроси прив'язки
Засоби підтримки стандартного набору макросів знаходяться у файлі spring- webmvc.jar
для FreeMarker,
тому вони завжди доступні для відповідного настроєного додатка.
Деякі макроси, визначені в бібліотеках шаблонізації в Spring, вважаються внутрішніми (приватними), але в
визначеннях макросів такого обмеження немає, що робить все макроси видимими для коду, який робить виклик, і
користувацьких шаблонів. Наступні розділи присвячені лише макросам, які необхідно викликати безпосередньо із
шаблонів. Якщо тобі потрібно переглянути код макросу безпосередньо, файл називається spring.ftl
і
знаходиться в пакеті org.springframework.web.servlet.view.freemarker
.
Просте прив'язування
У твоїх HTML-формах на базі шаблонів FreeMarker, які діють як подання форми для контролера Spring MVC, можна
використовувати код, подібний до того, що представлений в наступному прикладі, для прив'язки до значень полів і
виведення на екран повідомлень про помилки кожного поля введення аналогічно еквіваленту JSP. У цьому прикладі
показано подання personForm
:
<!-- Макроси FreeMarker повинні бути імпортовані в простір імен.
Ми рекомендуємо дотримуватись параметра "spring". -->
<#import "/spring.ftl" as spring/>
<html>
...
<form action="" method="POST">
Name:
<@spring.bind "personForm.name"/>
<input type="text"
name="${spring.status.expression}"
value="${spring.status.value?html}"/><br/>
<#list spring.status.errorMessages as error> <b>${error}</b> <br/> </#list>
<br />
...
<input type="submit" value="submit"/>
</form>
...
</html>
<@spring.bind>
вимагає аргумент "path", який складається з імені твого об'єкта команди (це
"command", якщо не змінити його в конфігурації контролера), за яким слідує точка та ім'я поля об'єкта
команди, до якого ти хочеш здійснити прив'язку. Також можна використовувати вкладені поля, наприклад, command.address.street
.
Макрос bind передбачає логіку HTML-екранування за замовчуванням, встановлену параметром defaultHtmlEscape контексту
ServletContext
у web.xml.
Альтернативна форма макросу <@spring.bindEscaped>
приймає другий аргумент, який явно вказує,
чи слід використовувати HTML-екранування в повідомленнях про помилку визначення статусу чи значення. Залежно від
необхідності можна встановити значення true
або false
. Додаткові макроси для роботи з
формами полегшують використання HTML-екранування, і тобі варто використовувати ці макроси скрізь, де це можливо.
Вони описані в наступному розділі.
Макроси введення
Додаткові допоміжні макроси для FreeMarker спрощують прив'язку та генерацію форм (включно з виведенням на екран помилок валідації). Немає необхідності використовувати ці макроси для створення полів введення форми: їх можна змішувати та поєднувати за допомогою простого HTML або прямих викликів макросів прив'язки Spring, про які ми розповідали раніше.
У цій таблиці доступних макросів наведено визначення шаблону FreeMarker Template (FTL) та список параметрів, які приймає кожен із них:
макрос | Визначення FTL |
---|---|
|
<@spring.message code/> |
|
<@spring.messageText code, text/> |
|
<@spring.url relativeUrl/> |
|
<@spring.formInput path, attributes, fieldType/> |
|
<@spring.formHiddenInput path, attributes/> |
|
<@spring.formPasswordInput path, attributes/> |
|
<@spring. formTextarea path, attributes/> |
|
<@spring.formSingleSelect path, options, attributes/> |
|
<@spring.formMultiSelect path, options, attributes/> |
|
<@spring.formRadioButtons path, options separator, attributes/> |
|
<@spring.formCheckboxes path, options, separator, attributes/> |
|
<@spring.formCheckbox path, attributes/> |
|
<@spring.showErrors separator, classOrStyle/> |
formHiddenInput
та formPasswordInput
фактично немає потреби, тому що ти можеш використовувати звичайний макрос formInput
, якщо вкажеш
hidden
або password
як значення параметра fieldType
.
Параметри будь-якого з вищезгаданих макросів мають зрозуміле значення:
path
: ім'я поля для прив'язки (тобто. "command.name")options
:Map
всіх доступних значень, які можна обрати в полі введення. Ключі Map є значеннями, які передаються назад з форми і прив'язуються до об'єкта команди. Об'єкти Map, що зберігаються поряд із ключами, є мітками, що відображаються у формі для користувача, і можуть відрізнятися від відповідних значень, що повертаються формою. Зазвичай така Map надається контролером як довідкові дані. Ти можеш використовувати будь-яку реалізацію Map в залежності від логіки роботи. Для строго відсортованих Map можна використовувати SortedMap (наприклад, TreeMap) з відповідним Comparator, а для довільних Map, які повинні повертати значення в порядку вставки, використовуй LinkedHashMap або LinkedMap з commons-collections.separator
: якщо кілька опцій доступні у вигляді окремих елементів (перемикачі або прапорці), цей параметр представляє послідовність символів, що використовуються для поділу кожного з них у списку (наприклад,<br>
).attributes
: додатковий рядок довільних тегів або тексту для включення в сам HTML-тег. Цей рядок буквально повторюється макросом. Наприклад, у поліtextarea
можна передати атрибути (наприклад, 'rows="5" cols="60"') або інформацію про стиль, наприклад, 'style="border:1px solid silver"'.classOrStyle
: для макросуshowErrors
– ім'я класу CSS, який використовується в елементіspan,
обгортаючи кожну помилку. Якщо інформація не надана (або значення порожнє), помилки обертаються в теги<b></b>
.
У наступних розділах наведено приклади макросів.
Поля введення
Макро formInput
приймає параметр path(command.name
) та додатковий параметр attributes
(який у наступному прикладі порожній). Цей макрос, як і інші макроси генерації форм, виконує неявну прив'язку
Spring до параметра "path". Прив'язка залишається дійсною доти, доки не буде здійснено нову прив'язку, тому
макросу showErrors
не потрібно знову передавати параметр "шляху" — він працює з полем, для якого
прив'язка була створена востаннє.
Макрос showErrors
приймає параметр-розділювач (символи,
які використовуються для розділення кількох помилок у даному полі), а також приймає другий параметр: цього разу —
ім'я класу або атрибут стилю. Зверни увагу, що FreeMarker може встановити значення за замовчуванням для
параметра "attributes". У наступному прикладі показано, як використовувати макроси formInput
та
showErrors
:
<@spring.formInput "command.name"/>
<@spring.showErrors "<br>"/>
У наступному прикладі показано виведення фрагменту форми з генерацією поля імені та виведенням помилки валідації після того, як форму було відправлено без значення в полі. Валідація відбувається через фреймворк Validation у Spring.
Створюваний HTML схожий на наступний приклад:
Name:
<input type="text" name="name" value="">
<br>
<b>required</b>
<br>
<br>
Макрос formTextarea
працює так само, як і макрос formInput
, і приймає той самий перелік
параметрів. Зазвичай другий параметр (attributes
) використовується для передачі інформації про
стиль або атрибути rows
і cols
для textarea
.
Поля вибору
Ти можеш використовувати чотири макроси для полів вибору, щоб генерувати звичайні вхідні дані вибору значень інтерфейсу користувача у своїх HTML-формах :
formSingleSelect
formMultiSelect
formRadioButtons
formCheckboxes
Кожен із чотирьох макросів приймає Map
опцій, яка містить значення для поля форми та мітку, що
відповідає цьому значенню. Значення та мітка можуть бути однаковими.
Наступний приклад стосується перемикачів у FTL. Базовий об'єкт форми задає для цього поля значення за замовчуванням "London", тому валідація не потрібна. Коли форма відображається, весь список міст для вибору надається як довідкові дані в моделі під ім'ям "cityMap". У наступному лістингу показаний приклад:
...
Town:
<@spring.formRadioButtons "command.address.town", cityMap, ""/><br><br>
У попередньому лістингу відображається рядок перемикачів, по одному для кожного значення cityMap
, і
використовується роздільник ""
. Жодних додаткових атрибутів не привласнюється (останнього параметра
макросу немає). cityMap
використовує ту саму String
для кожної пари ключ-значення в
Map. Ключі Map — це те, що форма фактично надсилає як параметри POST
-запиту. Значення Map — це
позначки, які бачить користувач. У попередньому прикладі, враховуючи список із трьох відомих міст і значення за
замовчуванням у базовому об'єкті форми, HTML виглядає так:
Town:
<input type="radio" name="address.town" value="London">London</input>
<input type="radio" name="address.town" value="Paris" checked="checked">Paris</input>
<input type="radio" name="address.town" value="New York">New York</input>
Якщо твоя програма передбачає роботу з містами за внутрішніми кодами (наприклад), то можна створити Map кодів з відповідними ключами, як показано в наступному прикладі:
protected Map<String, ?> referenceData(HttpServletRequest request) throws Exception {
Map<String, String> cityMap = new LinkedHashMap<>();
cityMap.put("LDN", "London");
cityMap.put("PRS", "Paris");
cityMap.put("NYC", "New York");
Map<String, Object> model = new HashMap<>();
model.put("cityMap", cityMap);
return model;
}
protected fun referenceData(request: HttpServletRequest): Map<String, *> {
val cityMap = linkedMapOf(
"LDN" to "London",
"PRS" to "Paris",
"NYC" to "New York"
)
return hashMapOf("cityMap" to cityMap)
}
Тепер код виводить дані, де значеннями перемикача є відповідні коди, але користувач, як і раніше, бачить зручніші назви міст, як показано нижче:
Town:
<input type="radio" name="address.town" value="LDN">London</input>
<input type="radio" name="address.town" value="PRS" checked="checked">Paris</input>
<input type="radio" name="address.town" value="NYC">New York</input>
HTML-екранування
Використання за замовчуванням макросів форми, описаних раніше, призводить до створення HTML-елементів, які
відповідають стандарту HTML 4.01 і використовують значення за замовчуванням для HTML-екранування, визначене у
файлі web.xml
, яке використовується засобами підтримки прив'язки Spring. Щоб зробити елементи
сумісними з XHTML або перевизначити значення HTML-екранування за замовчуванням, можна вказати дві змінні у
твоєму шаблоні (або у твоїй моделі, де їх бачать твої шаблони). Перевага їх зазначення в шаблонах полягає в
тому, що
їх
можна змінити на інші значення пізніше під час обробки шаблону, щоб забезпечити різну логіку роботи для
різних полів твоєї форми. Щоб перейти до режиму сумісності з XHTML для твоїх тегів, встанови значення true для
моделі або контекстної змінної з ім'ям xhtmlCompliant
, як показано в наступному прикладі:
<#-- для FreeMarker -->
<#assign xhtmlCompliant = true>
Після обробки цієї директиви всі елементи, створені макросами Spring, будуть сумісні зі стандартом XHTML.
Аналогічним чином можна встановити HTML-екранування для кожного поля, як показано в наступному прикладі:
<#-- until this point, default HTML escaping is used -->
<#assign htmlEscape = true>
<#-- next field will use HTML escaping -->
<@spring.formInput "command.name"/>
<#assign htmlEscape = false in spring>
<#-- all future fields will be bound with HTML-екранування off -->
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ