К основному контенту

Apache Tiles: Основы

Здравствуйте!
В работе я часто использую фреймворк Apache Tiles. Де-факто он является основной технологией для создания UI в  проектах над которыми я работаю. В связи с этим хотелось бы поделиться наработанным опытом работы с данной технологией. В цикле будет несколько статей, в которых я разберу что такое этот Tiles, как его настраивать, как правильно использовать и как его задружить со Spring MVC.  Первые несколько статей - по сути вольный пересказ официальной документации с моими примерами, которые можно будет запустить у себя на компьютере, так что если кому нравится работать с первоисточником - милости прошу.

Содержание

Часть 1. Основы.




Часть 1. Основы


Фреймворк Apache Tiles это реализация паттерна Composite View. Данный паттерн формализует типичное использование веб-страниц, подразумевая что они построены по одинаковым принципам и имеют одинаковую структуру.  Разбивая страницы на независимые блоки мы создаем шаблоны, составленные из этих блоков. Как правило страницы состоят из сходных элементов и при переходе с одной странички на другую нам надо поменять только один блок - контент. С помощью Tiles очень легко определить общие составные части таких страниц и создать шаблон, который будет использоваться для рендеринга.

Итак, приступим к конфигурированию проекта.
Вы можете начать с начала и самостоятельно создать мавен веб проект. О том как это делается можно почитать тут.
Или же вы можете скачать готовый проект из моего репозитория.
В терминале выполните следующие команды:
 
> git clone https://imilienko@bitbucket.org/imilienko/apache-tiles-tutorial.git
> cd ./apache-tiles-tutorial
> git checkout step0

Файловая структура должна получиться как на картинке. (Прим. Файлы и директории выделенные синим - добавленные в процессе работы над проектом).


Далее идем в pom.xml и добавляем зависимость 

<dependency>
   <groupId>org.apache.tiles</groupId>
   <artifactId>tiles-extras</artifactId>
   <version>3.0.7</version>
</dependency>

Это общая зависимость - она подтягивает все необходимые для работы артефакты, самое то для старта.

Теперь нам нужно зарегистрировать листенер и сервлет. Листенер нам нужен для того чтобы поднять Tiles контейнер, а сервлет - чтобы маршрутизировать ссылки и отдавать готовые страницы. Регистрацию их мы производим в web.xml

<web-app>
  <display-name>Tiles Tutor</display-name>
  <listener>
    <listener-class>org.apache.tiles.extras.complete.CompleteAutoloadTilesListener</listener-class>
  </listener>

  <servlet>
    <servlet-name>Tiles Dispatch Servlet</servlet-name>
    <servlÏt-class>org.apache.tiles.web.util.TilesDispatchServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Tiles Dispatch Servlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  
</web-app>

Отлично! Теперь почти все готово, осталось создать сами страницы.

В  Apache Tiles страница как сущность состоит из трех элементов - шаблон, атрибут, определение.

Шаблон - это jsp/jspx страница на которой вы определяете структуру вашего UI, у него могут присутствовать или отсутствовать атрибуты;
Атрибут - это та часть шаблона, в которую можно вставить что угодно, хоть простую строку, хоть другое определение;

Как пример можно рассмотреть классическую структуру сайта


Такую страницу можно реализовать следующим шаблоном

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<table>
  <tr>
    <td colspan="2">
      <tiles:insertAttribute name="header" />
    </td>
  </tr>
  <tr>
    <td>
      <tiles:insertAttribute name="menu" />
    </td>
    <td>
      <tiles:insertAttribute name="body" />
    </td>
  </tr>
  <tr>
    <td colspan="2">
      <tiles:insertAttribute name="footer" />
    </td>
  </tr>
</table>

Определение в свою очередь -  это собственно страница, которая отдается  конечному пользователю. Определение состоит из шаблона и частично или полностью заполненных атрибутов. Если атрибуты заполнены не полностью, то это абстрактное определение и оно может использоваться как основа для создания расширенных определений,
Пример определения:
<definition name="myapp.homepage" template="/layouts/classic.jsp">
  <put-attribute name="header" value="/tiles/banner.jsp" />
  <put-attribute name="menu" value="/tiles/common_menu.jsp" />
  <put-attribute name="body" value="/tiles/home_body.jsp" />
  <put-attribute name="footer" value="/tiles/credits.jsp" />
</definition>

В нашем конкретном случае, так как мы используем сервлет-диспетчер из коробки, имя определения будет контекстным путем для страницы, то есть, если мы хотим увидеть страницу созданную из определения, приведенного выше, то нам надо перейти по адресу http://://myapp.homepage.

Итак, теперь создадим  парочку шаблонов.
Создадим основной шаблон, который определяет структуру страниц нашего приложения
{base.dir}/src/main/webapp/layout/classic.html

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ page contentType="text/html; UTF-8" %>
<html>
<head>
    <title>Tiles Example</title>
    <link rel="stylesheet" type="text/css" href="static/css/style.css"/>
</head>
<body>
<table>
    <tr>
        <td colspan="2">
            <tiles:insertAttribute name="header" />
        </td>
    </tr>
    <tr>
        <td>
            <tiles:insertAttribute name="menu" />
        </td>
        <td>
            <tiles:insertAttribute name="body" />
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <tiles:insertAttribute name="footer" />
        </td>
    </tr>
</table>
</body>
</html>

Как видим, тут у нас четыре атрибута, которые определяют основные элементы страницы - хедер, меню, контент, футер. Создадим шаблоны и для них

{base.dir}/src/main/webapp/tiles/heade.jsp
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ page contentType="text/html; UTF-8" %>

<header >
    <h1>Apache tiles Base tutorial</h1>
</header>


{base.dir}/src/main/webapp/tiles/menu.jsp

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ page contentType="text/html; UTF-8" %>

<aside >
    <ul>
        <li>
            <a href="/item_one">Item one</a>
        </li>
        <li>
            <a href="/item_two">Item two</a>
        </li>
        <li>
            <a href="/path/to/item_three">Item three</a>
        </li>
    </ul>
</aside>


{base.dir}/src/main/webapp/tiles/body.jsp

<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ page contentType="text/html; UTF-8" %>

<main>
    <p><tiles:insertAttribute name="body_text" defaultValue="Girl look at this body - I work out!"/> </p>
</main>

{base.dir}/src/main/webapp/tiles/footer.jsp
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%@ page contentType="text/html; UTF-8" %>

<footer >
    <small>©Imilienko 2017</small>
</footer>

Как видно, в body.jsp у нас есть атрибутик, body_text со значением по-умолчанию. Это значит, что если мы в качестве атрибута в определении ничего не передадим, то  на этом место будет просто вставлена строка "Girl look at this body - I work out!".

Осталось только подготовить определения.
По-умолчанию Tiles читает  определения  из файла WEB-INF/tiles.xml. Если подключен слушатель CompleteAutoloadTilesListener, то чтение производится из любого файла соответствующего WEB-INF/tiles*.xml. Если в этом случае вы положили туда парочку таких файлов, то они объединятся в один.  Таким образом можно разбивать определения по нескольким файлам, дабы не смешивать, например, элементы и блоки, если вы пользуетесь  БЭМ.
У нас проект стартовый и маленький поэтому мы все сложим в один WEB-INF/tiles.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
        "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN"
        "http://tiles.apache.org/dtds/tiles-config_3_0.dtd">
<tiles-definitions>
    <definition name="classic" template="/layouts/classic.jsp">
        <put-attribute name="header" value="/tiles/header.jsp"/>
        <put-attribute name="menu" value="/tiles/menu.jsp"/>
        <put-attribute name="body" value="/tiles/body.jsp"/>
        <put-attribute name="footer" value="/tiles/footer.jsp"/>
    </definition>

    <definition name="" extends="classic"></definition>

    <definition name="item_one" extends="classic">
        <put-attribute name="body">
            <definition template="/tiles/body.jsp">
                <put-attribute name="body_text" value="This item one, man!"/>
            </definition>
        </put-attribute>
    </definition>

    <definition name="item_two" extends="classic">
        <put-attribute name="body">
            <definition template="/tiles/body.jsp">
                <put-attribute name="body_text" value="This yet another item , man!"/>
            </definition>
        </put-attribute>
    </definition>

    <definition name="path/to/item_three" extends="classic">
        <put-attribute name="body">
            <definition template="/tiles/body.jsp">
                <put-attribute name="body_text" value="Yey! You here, man!"/>
            </definition>
        </put-attribute>
    </definition>
</tiles-definitions>

Как видно у нас тут несколько определений, соответственно несколько страниц. Определение, именованное как classic - основное, оно определяет структуру страниц веб-приложения, содержит все неизменяемые элементы (хедер и пр.). Определение без имени выступает в качестве главной страницы. Остальные определения, в том числе и главная страница наследуют определению classic,  получая от него структуру и заменяя только содержимое блока body.

Теперь можно запускать! Деплоим на томкат и получаем:





УРА! Все работает!  Как видите, все проще, чем кажется.

Если возникли вопросы или трудности, пишите в комменты или на почту
igormilienko@yandex.ru.
Еще раз ссылка на git  репозиторий
https://bitbucket.org/imilienko/apache-tiles-tutorial

Комментарии

Популярные сообщения из этого блога

Какую версию Jetty я использую?

Jetty 9 - самая свежая версия сервера с большим количеством улучшений по сравнению с предыдущими версиями. Данная документация фокусируется как раз на версии Jetty 9. Мы очень рекомендуем использовать версию 9, так как именно она будет поддерживаться и улучшаться в течении нескольких лет.