Вышло долгожданное обновление Velocity: шаблонить стало немного проще

    Обзор новых возможностей шаблонного движка


    Первого декабря 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.

    Ну и резюмируя, не могу не отметить: «Жить стало лучше, жить стало веселей»!
    Поделиться публикацией

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

      +2
      Статья понравилась. Сам пользую Freemarker
      Может перенести сюда?
        0
        > Статья понравилась.

        Спасибо, сторалсо :)

        > Может перенести сюда?

        Дак я бы с удовольствием, да кармы не хватает. Мой первый пост на Хабре.
          +1
          Подростет — кидайте в тематический блог
            0
            Хорошо, спасибо, буду иметь в виду.
        +1
        Было бы совсем прекрасно если бы NVelocity обновили в след за Velocity.
          +1
          Да, Velocity — удобная штука. Если захочется большей выразительности, то можете посмотреть на Groovy Templates: groovy.codehaus.org/Groovy+Templates
            0
            Вы знаете, по поводу Groovy может выйти интересная полемика. По моему убеждению, шаблонизация на базе рефлексии дает оптимальный компромис между «статической» и «динамической» программными парадигмами: еще (почти) все под контролем, и при этом полно свободы. Тогда как еще маленький шаг влево — и при иллюзии абсолютной свободы ты уже на самом деле крепко повязан тотальной зависимостью от тестового харнеса (harness), потому как других средств контроля целостности кода у тебя не остается.

            ИМХО.
              0
              Шаблоны всё равно статически никто не проверяет. Да и результаты ошибки менее фатальны. ИМХО.
              0
              жаль gsp пока недоступно без grails :(
                0
                А зачем он для темплейтов? О_о ИМХО Template Engines за глаза хватает. Там тебе и ветвления, и итерации…
              0
              Как у вас, явщиков, все заморочно! То ли дело в пхп — куча шаблонизатлоров всех видов, и все в разы проще!))
                0
                За обзор спасибо, но юзать эту убогий фреймворк в проектах никому не рекоммендую.

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое