Оглавление
Хотя стандартный диалект позволяет нам делать почти все с использованием атрибутов тегов, бывают ситуации, когда мы можем предпочесть писать выражения непосредственно в наши HTML-тексты. Например, мы могли бы предпочесть написать это:
… вместо этого:
Выражения между [[...]] или [(...)] считаются встроенными выражениями, и внутри них мы можем использовать любое выражение, которое также было бы действительным в атрибуте th:text или th:utext.
Обратите внимание, что, хотя [[...]] соответствует th:text (то есть результат будет с HTML-экранированным / HTML-escaped), [(...)] соответствует th:utext и не будет выполнять HTML-экранирование / HTML-escaping. Итак, с переменной, такой как msg = 'This is <b>great!</b>', учитывая этот фрагмент:
В результате теги <b> не будут экранированы, поэтому результат:
Чтобы избежать этого:
Результат будет HTML-экранированным:
Обратите внимание, что текстовая вставка по умолчанию активна в теле каждого тега в нашей разметке — не сами теги, поэтому нам нечего делать, чтобы ее включить (сделать активной).
Вставка против естественных шаблонов / Inlining vs natural templates
Если вы пришли из других механизмов шаблонов, в которых этот способ вывода текста является нормой, вы можете спросить: почему мы не делаем это с самого начала? Это меньше кода, чем все те th:text атрибуты!
Но будьте осторожны, потому что, хотя вы можете найти встраивание интересным, вы всегда должны помнить, что встроенные выражения будут отображаться дословно в ваших HTML-файлах при их открытии статически, поэтому вы, вероятно, не сможете использовать ими в качестве прототипов дизайна!
Разница между тем, как браузер будет статически отображать наш фрагмент кода без использования встраивания:
… и с использованием встраивания:
… совершенно очевидна разница с точки зрения полезности дизайна.
Отключение встраивания
Однако этот механизм может быть отключен, поскольку на самом деле могут быть случаи, когда мы хотим выводить последовательности [[...]] или [(...)] без обработки содержимого в качестве выражения. Для этого мы будем использовать th:inline=«none»:
Результатом будет:
Вставка текста очень похожа на только что увиденную функцию выражения, но на самом деле она добавляет больше мощности. Текст должен быть включен явно с помощью th:inline=«text».
Вставка текста не только позволяет нам использовать те же встроенные выражения, которые мы только что видели, но фактически обрабатывает теги, как если бы они были шаблонами, обработанными в режиме шаблона TEXT, что позволяет нам выполнять текстовую логику шаблона (а не только выходные выражения).
Мы увидим больше об этом в следующей главе о режимах текстового шаблона.
JavaScript inlining позволяет лучше интегрировать блоки JavaScript <script> в шаблоны, обрабатываемые в режиме шаблона HTML.
Как и при вставке текста, это фактически эквивалентно обработке содержимого скриптов, как если бы они были шаблонами в режиме шаблона JAVASCRIPT, и поэтому вся мощь режимов текстовых шаблонов (см. cледующую главу) будет под рукой. Однако в этом разделе мы сосредоточимся на том, как можем использовать режим для добавления вывода наших выражений Thymeleaf в блоки JavaScript.
Этот режим должен быть явно включен с помощью th:inline=«javascript»:
Результатом станет:
Две важные вещи необходимо отметить в приведенном коде:
Во-первых, эта вставка JavaScript не только выводит требуемый текст, но и заключает в него кавычки и экранирует JavaScript содержимое, так что результаты выражения выводятся как хорошо сформированный литерал JavaScript.
Во-вторых, это происходит потому, что мы выводим выражение ${session.user.name} как экранированное, т. е. используя выражение с двойной скобкой: [[${session.user.name}]]. Если вместо этого мы использовали unescaped как:
Результат был бы таким:
… который является неправильным кодом JavaScript. Но вывод чего-то неизолированного может быть тем, что нам нужно, если мы создаем части нашего скрипта посредством добавления встроенных выражений, поэтому хорошо иметь этот инструмент под рукой.
Естественные шаблоны JavaScript
Упомянутый интеллектуальный механизма разработки JavaScript намного больше, чем просто применение JavaScript-специфического экранирования и вывод результатов выражения как допустимых литералов.
Например, мы можем обернуть наши (экранированные) встроенные выражения в комментарии JavaScript так:
И Thymeleaf будет игнорировать все, что мы написали после комментария и до точки с запятой (в данном случае «Gertrud Kiwifruit»), поэтому результат выполнения этого будет выглядеть точно так же, как если бы мы не использовали комментарии:
Но еще раз посмотрим на оригинальный код шаблона:
Обратите внимание на этот валидный код JavaScript. И он отлично выполнится при открытии файла шаблона статическим образом (без его выполнения на сервере).
Итак, что мы имеем здесь — это способ сделать естественные шаблоны JavaScript!
Расширенная встраивание и сериализация JavaScript
Важно отметить, что JavaScript-inlining заключается в том, что это выполнение выражения является интеллектуальным и не ограничивается строками. Thymeleaf правильно напишет в синтаксисе JavaScript следующие типы объектов:
Например, следующий код:
выражение ${session.user} преобразуется к объекту User, и Thymeleaf корректно конвертирует его в Javascript синтаксис:
То, как выполняется эта сериализация JavaScript, — это реализация интерфейса org.thymeleaf.standard.serializer.IStandardJavaScriptSerializer, который может быть сконфигурирован в экземпляре StandardDialect, используемого в движке шаблона.
По умолчанию реализация этого механизма сериализации JS будет искать библиотеку Jackson в пути к классам и, если она будет присутствовать, будет использовать ее. Если нет, он применит встроенный механизм сериализации, который будет отвечать потребностям большинства сценариев и даст аналогичные результаты (но менее гибко).
Thymeleaf также позволяет использовать вставку в тегах CSS <style>, например:
Например, скажем, у нас есть две переменные, установленные на два разных значения String:
Можем использовать их:
Результатом будет:
Обратите внимание, что CSS-встраивание также обладает некоторым интеллектом, как JavaScript-встраивание. В частности, выражения, выводимые с помощью экранированных выражений типа [[${classname}]], будут экранированы как идентификаторы CSS. Вот почему наш класс = 'main elems' превратился в main\ elems в фрагменте кода выше.
Расширенные функции: естественные шаблоны CSS и т. д.
В эквивалентном способе, описанном ранее для JavaScript, CSS-inlining также позволяет нашим тегам <style> работать как статически, так и динамически, то есть как естественным шаблонам CSS путем обертывания встроенных выражений в комментариях. Смотрите:
12 Встраивание / Inlining
12.1 Выражения встраивания / Expression inlining
Хотя стандартный диалект позволяет нам делать почти все с использованием атрибутов тегов, бывают ситуации, когда мы можем предпочесть писать выражения непосредственно в наши HTML-тексты. Например, мы могли бы предпочесть написать это:
<p>Hello, [[${session.user.name}]]!</p>
… вместо этого:
<p>Hello, <span th:text="${session.user.name}">Sebastian</span>!</p>
Выражения между [[...]] или [(...)] считаются встроенными выражениями, и внутри них мы можем использовать любое выражение, которое также было бы действительным в атрибуте th:text или th:utext.
Обратите внимание, что, хотя [[...]] соответствует th:text (то есть результат будет с HTML-экранированным / HTML-escaped), [(...)] соответствует th:utext и не будет выполнять HTML-экранирование / HTML-escaping. Итак, с переменной, такой как msg = 'This is <b>great!</b>', учитывая этот фрагмент:
The message is "[(${msg})]"
В результате теги <b> не будут экранированы, поэтому результат:
<p>The message is "This is <b>great!</b>"</p>
Чтобы избежать этого:
<p>The message is "[[${msg}]]"</p>
Результат будет HTML-экранированным:
<p>The message is "This is <b>great!</b>"</p>
Обратите внимание, что текстовая вставка по умолчанию активна в теле каждого тега в нашей разметке — не сами теги, поэтому нам нечего делать, чтобы ее включить (сделать активной).
Вставка против естественных шаблонов / Inlining vs natural templates
Если вы пришли из других механизмов шаблонов, в которых этот способ вывода текста является нормой, вы можете спросить: почему мы не делаем это с самого начала? Это меньше кода, чем все те th:text атрибуты!
Но будьте осторожны, потому что, хотя вы можете найти встраивание интересным, вы всегда должны помнить, что встроенные выражения будут отображаться дословно в ваших HTML-файлах при их открытии статически, поэтому вы, вероятно, не сможете использовать ими в качестве прототипов дизайна!
Разница между тем, как браузер будет статически отображать наш фрагмент кода без использования встраивания:
Hello, Sebastian!
… и с использованием встраивания:
Hello, [[${session.user.name}]]!
… совершенно очевидна разница с точки зрения полезности дизайна.
Отключение встраивания
Однако этот механизм может быть отключен, поскольку на самом деле могут быть случаи, когда мы хотим выводить последовательности [[...]] или [(...)] без обработки содержимого в качестве выражения. Для этого мы будем использовать th:inline=«none»:
<p th:inline="none">A double array looks like this: [[1, 2, 3], [4, 5]]!</p>
Результатом будет:
<p>A double array looks like this: [[1, 2, 3], [4, 5]]!</p>
12.2 Встраивание текста
Вставка текста очень похожа на только что увиденную функцию выражения, но на самом деле она добавляет больше мощности. Текст должен быть включен явно с помощью th:inline=«text».
Вставка текста не только позволяет нам использовать те же встроенные выражения, которые мы только что видели, но фактически обрабатывает теги, как если бы они были шаблонами, обработанными в режиме шаблона TEXT, что позволяет нам выполнять текстовую логику шаблона (а не только выходные выражения).
Мы увидим больше об этом в следующей главе о режимах текстового шаблона.
12.3 Встраивание JavaScript
JavaScript inlining позволяет лучше интегрировать блоки JavaScript <script> в шаблоны, обрабатываемые в режиме шаблона HTML.
Как и при вставке текста, это фактически эквивалентно обработке содержимого скриптов, как если бы они были шаблонами в режиме шаблона JAVASCRIPT, и поэтому вся мощь режимов текстовых шаблонов (см. cледующую главу) будет под рукой. Однако в этом разделе мы сосредоточимся на том, как можем использовать режим для добавления вывода наших выражений Thymeleaf в блоки JavaScript.
Этот режим должен быть явно включен с помощью th:inline=«javascript»:
<script th:inline="javascript">
...
var username = [[${session.user.name}]];
...
</script>
Результатом станет:
<script th:inline="javascript">
...
var username = "Sebastian \"Fruity\" Applejuice";
...
</script>
Две важные вещи необходимо отметить в приведенном коде:
Во-первых, эта вставка JavaScript не только выводит требуемый текст, но и заключает в него кавычки и экранирует JavaScript содержимое, так что результаты выражения выводятся как хорошо сформированный литерал JavaScript.
Во-вторых, это происходит потому, что мы выводим выражение ${session.user.name} как экранированное, т. е. используя выражение с двойной скобкой: [[${session.user.name}]]. Если вместо этого мы использовали unescaped как:
<script th:inline="javascript">
...
var username = [(${session.user.name})];
...
</script>
Результат был бы таким:
<script th:inline="javascript">
...
var username = Sebastian "Fruity" Applejuice;
...
</script>
… который является неправильным кодом JavaScript. Но вывод чего-то неизолированного может быть тем, что нам нужно, если мы создаем части нашего скрипта посредством добавления встроенных выражений, поэтому хорошо иметь этот инструмент под рукой.
Естественные шаблоны JavaScript
Упомянутый интеллектуальный механизма разработки JavaScript намного больше, чем просто применение JavaScript-специфического экранирования и вывод результатов выражения как допустимых литералов.
Например, мы можем обернуть наши (экранированные) встроенные выражения в комментарии JavaScript так:
<script th:inline="javascript">
...
var username = /*[[${session.user.name}]]*/ "Gertrud Kiwifruit";
...
</script>
И Thymeleaf будет игнорировать все, что мы написали после комментария и до точки с запятой (в данном случае «Gertrud Kiwifruit»), поэтому результат выполнения этого будет выглядеть точно так же, как если бы мы не использовали комментарии:
<script th:inline="javascript">
...
var username = "Sebastian \"Fruity\" Applejuice";
...
</script>
Но еще раз посмотрим на оригинальный код шаблона:
<script th:inline="javascript">
...
var username = /*[[${session.user.name}]]*/ "Gertrud Kiwifruit";
...
</script>
Обратите внимание на этот валидный код JavaScript. И он отлично выполнится при открытии файла шаблона статическим образом (без его выполнения на сервере).
Итак, что мы имеем здесь — это способ сделать естественные шаблоны JavaScript!
Расширенная встраивание и сериализация JavaScript
Важно отметить, что JavaScript-inlining заключается в том, что это выполнение выражения является интеллектуальным и не ограничивается строками. Thymeleaf правильно напишет в синтаксисе JavaScript следующие типы объектов:
- Strings
- Numbers
- Booleans
- Arrays
- Collections
- Maps
- Beans (объекты с геттером и сеттером)
Например, следующий код:
<script th:inline="javascript">
...
var user = /*[[${session.user}]]*/ null;
...
</script>
выражение ${session.user} преобразуется к объекту User, и Thymeleaf корректно конвертирует его в Javascript синтаксис:
<script th:inline="javascript">
...
var user = {"age":null,"firstName":"John","lastName":"Apricot",
"name":"John Apricot","nationality":"Antarctica"};
...
</script>
То, как выполняется эта сериализация JavaScript, — это реализация интерфейса org.thymeleaf.standard.serializer.IStandardJavaScriptSerializer, который может быть сконфигурирован в экземпляре StandardDialect, используемого в движке шаблона.
По умолчанию реализация этого механизма сериализации JS будет искать библиотеку Jackson в пути к классам и, если она будет присутствовать, будет использовать ее. Если нет, он применит встроенный механизм сериализации, который будет отвечать потребностям большинства сценариев и даст аналогичные результаты (но менее гибко).
12.4 CSS-вставка
Thymeleaf также позволяет использовать вставку в тегах CSS <style>, например:
<style th:inline="css">
...
</style>
Например, скажем, у нас есть две переменные, установленные на два разных значения String:
classname = 'main elems'
align = 'center'
Можем использовать их:
<style th:inline="css">
.[[${classname}]] {
text-align: [[${align}]];
}
</style>
Результатом будет:
<style th:inline="css">
.main\ elems {
text-align: center;
}
</style>
Обратите внимание, что CSS-встраивание также обладает некоторым интеллектом, как JavaScript-встраивание. В частности, выражения, выводимые с помощью экранированных выражений типа [[${classname}]], будут экранированы как идентификаторы CSS. Вот почему наш класс = 'main elems' превратился в main\ elems в фрагменте кода выше.
Расширенные функции: естественные шаблоны CSS и т. д.
В эквивалентном способе, описанном ранее для JavaScript, CSS-inlining также позволяет нашим тегам <style> работать как статически, так и динамически, то есть как естественным шаблонам CSS путем обертывания встроенных выражений в комментариях. Смотрите:
<style th:inline="css">
.main\ elems {
text-align: /*[[${align}]]*/ left;
}
</style>