Использование Struts Tiles + Spring Framework
18 июня 2007
Одной из фич Struts Framework, помимо MVC для веба, была библиотека тегов Tiles, идущая с ним. Тайлы много что могут, но главное что они помогают сделать наследования страниц. Да, так же как объекты, в корневом определяем базовые методы, а в предках что то переопределяем и добавляем новое.
При этом эта библиотека может использоваться и отдельно от Struts, она прекрасно интегрируется в Spring Framework.
Вот без тайлов как может выглядеть структура JSP страницы?
[инклюд хидера]
[тело страницы]
[инклюд футера]
Ну вроде так ничего сложного, типичный PHP стиль. А теперь допустим в хидере у нас что то меняется, например картинка раздела, подключается дополнительный css, JavaScript или еще что то. Вот тут все и начинается: в хидере пишется страшная логика охватывающая весь проект, которая, в зависимости от адреса, начинает что то включать/выключать, при инклюде передаются различные параметры, чтобы все это работало и т.д. Немного неудобно получается.
В Tiles это выглядело бы по другому, головной темплейт:
начало хидера
картинка с [адресом]
[вставить доп. код]
конец хидера
[вставить тело страницы]
футер
а далее, на прочих страницах мы пишем что наследуем головной хидер, и что у него заменяем адрес картинки, тело страницы и иногда доп. код. Значения по умолчанию этих полей настраиваются в конфигурационном файле тайлов, и могут быть пустыми.
Вот так все бы это выглядело в виде JSP кода:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="/tags/struts-tiles" prefix="tiles" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title><tiles:getAsString name="title"/></title>
<tiles:getAsString name="head" />
</head>
<body onload="<tiles:getAsString name="onLoad"/>">
<div id="header">
МойСуперПуперСайт!
<h1><tiles:getAsString name="title"/></h1>
</div>
<tiles:getAsString name="body" />
<div id="footer">
копирайты, об авторе или что там надо внизу страницы
</div>
</body>
</html>
Вот это вот <tiles:getAsString... и вставляет, определённые в наследнике, блоки данных.
далее страница которая хочет это наследовать выглядит так:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="/tags/struts-tiles" prefix="tiles" %>
<tiles:insert definition="layout.root" flush="false">
<tiles:put name="title">О сайте</tiles:put>
<tiles:put name="body" direct="true">
Всякий текст
</tiles:put>
</tiles:insert>
Можно рассматривать это как наследование страниц, только в объекте мы переопределяем методы, а здесь куски html.
Настройка tiles в spring
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles.TilesConfigurer"
lazy-init="false">
<property name="factoryClass">
<value>org.apache.struts.tiles.xmlDefinition.I18nFactorySet</value>
</property>
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
lazy-init="false">
<property name="requestContextAttribute"><value>requestContext</value></property>
<property name="viewClass">
<value>org.springframework.web.servlet.view.tiles.TilesView</value>
</property>
</bean>
В web.xml добавляем настройку кастомных jsp тегов:
<jsp-config>
<taglib>
<taglib-uri>/tags/struts-tiles</taglib-uri>
<taglib-location>/WEB-INF/struts-tiles.tld</taglib-location>
</taglib>
</jsp-config>
Настройка связей имен Tiles к файлам
Есть одна тонкость: полученные нами jsp напрямую не заработают если их указать в ModelAndView контроллера. Тут указывается лишь идентификатор тайла, а сами страницы настроены в WEB-INF/tiles.xml (это в нашем случае, а вообще в том файле который указан в значении definitions бина tilesConfigurer).
Это должен быть файлик примерно следующего вида:
<?xml version="1.0"?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">
<tiles-definitions>
<definition name="layout.error" path="/tiles/common/errorLayout.jsp"/>
<definition name="layout.simple" path="/tiles/common/simpleLayout.jsp">
<put name="head" value=""/>
</definition>
<definition name="common.header" path="/tiles/common/header.jsp"/>
<definition name="common.footer" path="/tiles/common/footer.jsp"/>
<definition name="/index" path="/index.jsp"/>
<definition name="user/login" path="/user/login.jsp"/>
<definition name="404" path="/errors/404.jsp"/>
</tiles-definitions>
где name это имя тайла, а path это путь к существующей jsp. И приходится вот так прописывать все страницы, что нифига неудобно, особенно раздражает когда name и path на самом деле совпадают(как для index и user/login, отличается лишь тем что мне в name лень писать .jsp).
В общем как-то вот так.

августа 21, 2007 в 18:46
>Вот это вот tiles:getAsString... и вставляет, определённые в наследнике, блоки данных.
А что мешает вставить туда ПХП-переменные? Честно говоря, у меня складываеся впечателение, что ПХП-программеры изобретают велосипед и создают себе проблемы. Если в одном файле встречается больше одного тега
ноября 30, 2007 в 06:08
Ничего не мешает. И этот элемент можно считать вставкой переменной.