Обзор новых возможностей шаблонного движка
Первого декабря 2008 г. Apache объявила о выпуске новой версии давно не обновлявшегося шаблонного движка Velocity, за номером 1.6, а еще двумя неделями позже появился апдейт со свежими фиксами, Velocity Engine 1.6.1. Те, кто используют Velocity в своих проектах, будут рады узнать о новых возможностях, появившихся в новой версии. Те же, кто Velocity не используют, возможно, откроют для себя новый полезный инструмент.
Краткая справка
Apache Velocity — программный продукт, состоящий из ряда Java-библиотек. Продукт разрабатывается и поддерживается в рамках Apache Software Foundation, и распространяется как программное обеспечение с открытым кодом под лицензией Apache License 2.0. Главным компонентом продукта является Velocity Engine — библиотека, позволяющая формировать выходные тексты на основе шаблонов, что в просторечии именуется шаблонным движком.
Зачем нужны шаблонные движки
Вообще-то наиболее широкое применение шаблонные движки находят в веб разработке, но проще всего показать пользу от их использования на примере формирования текста письма. Допустим, у нас есть база пользователей, и мы хотим разослать анонс нового продукта. Текст стандартный, меняется только имя, дата и название продукта. Открываем блокнот и пишем:
Дорогой $customer.name
Компания "Рога и Копыта" с радостью доводит до Вашего сведения, что $product.name поступил в свободную продажу! Спрашивайте в аптеках города.
$date
Служба маркетинга компании "Рога и Копыта"
Как вы уже догадались, $customer.name, $product.name и $date — суть переменные, вместо которых при формировании выходного текста будут подставлены реальные значения. Возникает вопрос: как передать эти значения шаблону? Делается это очень просто. В исходнике Java прописываем:
VelocityEngine velocity = new VelocityEngine();
velocity.init();
Template letter = velocity.getTemplate("letter.vm");
Date now = new Date();
Product product = someDAO.getLatestProduct();
List<Customer> customers = someDAO.getCustomers();
for (Customer customer : customers) {
VelocityContext vc = new VelocityContext();
vc.put("customer", customer);
vc.put("product", product);
vc.put("date", now);
StringWriter sw = new StringWriter();
letter.merge(vc, sw);
// делаем с полученным текстом что хотим
Как видите, ничего особо мудреного тут нет: объекты Java, каждый под своим ключом, закладываются в экземпляр VelocityContext, который по сути представляет собой обычный Map. Когда в процессе слияния контекста с шаблоном движок встречает в тексте переменную, он использует ее имя в качестве ключа, и извлекает по нему из мапы соответствующий объект. Телемаркет!
Разумеется, нет никаких проблем приспособить шаблоны и для генерации HTML-страниц, что многие с успехом и сделали в свое время, выбросив на свалку истории во многом геморройную технологию JSP. Детальное описание языка шаблонов VTL и инструкцию по его использованию можно найти на сайте разработчика.
Но это все была предыстория. А теперь о собственно новой версии. На радость разработчикам, в 1.6 появился ряд долгожданных вкусностей. Рассмотрим их по порядку.
1. Директива #evaluate
Вот простой и жизненный пример: допустим, в базе хранится текст статьи. Где-то в середине мы хотим дать врезку с некими живыми данными: скажем, с результатами интернет-голосования. Это нетрудно: достаточно в нужном месте подключить файл шаблона, который выводит результаты в форме HTML:
#parse("poll.vm")
Беда, однако, в том, что если мы поместим текст статьи как обычную переменную ($article.text), ее содержимое тупо выведется на странице как есть. То есть вместо красивой диаграммы читатель увидит невразумительное #parse(«poll.vm»). Чтобы достичь нужного нам эффекта, нужно каким-то образом заставить Velocity интерпретировать текст статьи как код шаблона. Одной из немногих возможностей сделать это в прежних версиях было задействовать дополнительный компонент RenderTool из Velocity Toolbox. Что было, в принципе, терпимо, но несколько неудобно. С выходом 1.6 мы получили возможность делать это в одну строку:
#evaluate ($article.text)
2. Директива #define
Эта директива работает во многом подобно макросу, с той разницей, что куски шаблонного кода, определенные с его помощью, могут не только вызываться по месту, но и присваиваться контекстной переменной и далее использоваться там, где они окажутся нужны:
#define($block)Hello $who#end
#set($who = 'World!')
$block
Нужна ли нам такая конструкция на практике? Не так чтобы очень, но при ее наличии некоторые вещи можно реализовать более естественным способом. Например, что-нибудь типа шаблонного полиморфизма.
3. Директива #break
Мелочь, а приятно: теперь из цикла #foreach можно выскочить в одну строчку. При тех скудных средствах, которые имелись в Velocity для выражения логики управления, добавление целой новой директивы — уже огромный прорыв.
4. Возможность организовывать макросы в файлы
Одним из досадных ограничений старого Velocity было жестко фиксированное местоположение файла с макросами. Теперь макросы можно организовывать по своему усмотрению, и подключать их по мере необходимости:
#parse('mymacros.vm')
Вместо заключения
В этом обзоре были рассмотрены наиболее интересные новшества, появившиеся в Velocity Engine версии 1.6. Более подробно о новых возможностях движка можно прочитать на сайте продукта в разделе Changes.
Ну и резюмируя, не могу не отметить: «Жить стало лучше, жить стало веселей»!
![](https://habrastorage.org/getpro/habr/post_images/29d/59e/165/29d59e165acb265a7cb27f56e414082f.gif)