V tomto díle našeho seriálu se seznámíme se Sitemesh flow, tedy s principem, na jakém Sitemesh funguje. Ukážeme si, jak Sitemesh nasadit do aplikace, jeho konfiguraci a vysvětlíme si postup výběru jednotlivých dekorátorů. Nic více, nic méně.

Jak jsem psal v prvním díle tohoto miniseriálu, Sitemesh je založen na technologii javax.servlet.Filter. Třída, která implementuje toto rozhraní a která tvoří vstupní bod do Sitemeshe, se nazývá PageFilter.

Celý proces začíná tím, že webový kontejner příjme požadavek na stránku, která je v kontextu aplikace, na který je namapován PageFilter. Pokud se tak stane, požadavek je předán právě tomuto filtru, který vytvoří vlastní objekt odezvy, který pošle do aplikace spolu s daným požadavkem. Do tohoto objektu je zapouzdřena odpověď aplikace na daný požadavek a ten je vrácen zpět
PageFilteru.

Mapování PageFilteru na kontext aplikace ve WEB-INF/web.xml



<filter>
    </filter><filter -name>sitemesh</filter>
    <filter -class>com.opensymphony.module.sitemesh.filter.PageFilter</filter>

 
<filter -mapping>   
    </filter><filter -name>sitemesh</filter>
    <url -pattern>/*</url>
<filter -mapping> 


Jakmile se odezva vrátí PageFiltru, PageFilter zjistí typ jejího obsahu a vytvoří parser, kterým daný obsah bude zpracovávat. Sitemesh disponuje FastPageParserem, který je schopen zpracovávat obsah s content-type=”text/html”, ale nic programátorům nebrání naprogramovat si vlastní pro jakýkoli typ odezvy. Typ odezvy a její parser se specifikuje v dokumentu WEB-INF/sitemesh.xml.

Po rozparsování odezvy nastává fáze dekorační. Sitemesh obsahuje systém tzv. mapperů, tříd implementujících rozhraní DecoratorMapper, které určují, na základě jakých pravidel se bude vybírat správný dekorátor. Tyto mappery jsou definovány v souboru WEB-INF/sitemesh.xml. Každý mapper (definován v tomto souboru níže) je rodičem mapperu definovaného nad ním.

Definice mapperů ve WEB-INF/sitemesh.xml


<sitemesh>
   <property name="decorators-file" value="/WEB-INF/decorators.xml"/>
   <excludes file="${decorators-file}"/>
   <page -parsers>
     <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.FastPageParser" />
   </page>
   <decorator -mappers>
     <mapper class="com.opensymphony.module.sitemesh.mapper.LanguageDecoratorMapper">
       <param name="match.en" value="en" />
       <param name="match.cs" value="cs" />
     </mapper>
     <mapper class="com.opensymphony.module.sitemesh.mapper.AgentDecoratorMapper">
       <param name="match.MSIE" value="ie" />
       <param name="match.Mozilla" value="moz" />
     </mapper>
     <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
       <param name="config" value="${decorators-file}" />
     </mapper>
   </decorator>
</sitemesh>

Dekorátory mohou být vybírány např. na základě typu prohlížeče požadujícího stránku, na základě jazyka prohlížeče, hodnoty uchovávané v cookies či v session atd.

Pokud má Sitemesh vybrat dekorátor pro danou stránku, nejdříve vytvoří instanci prvního mapperu uvedeného v souboru WEB-INF/sitemesh.xml a volá jeho metodu getDecorator(). V této metodě se Sitemesh pokusí vybrat prodanou stránku správný dekorátor. Pokud se mu to nepodaří, pak volá stejnou metodu na jeho rodiči, tedy na mapperu definovaného v WEB-INF/sitemesh.xml pod ním. Tenhle postup se opakuje do nalezení správného dekorátoru pro danou stránku.

Pokud není v souboru WEB-INF/sitemesh.xml žádný mapper definován, či soubor WEB-INF/sitemesh.xml neexistuje, je vytvořen defaultní ConfigDecoratorMapper, který čte jména dekorátorů a jejich mapování ze souboru WEB-INF/decorators.xml, pokud není v souboru WEB-INF/sitemesh.xml definováno jinak.

Definice dekorátorů pro ConfigDecoratorMapper v WEB-INF/decorators.xml



<decorators defaultdir="WEB-INF/decorators">
   <decorator name="administrace" page="blog-admin.jsp">
     <pattern>/blog/administrace/*.jsp</pattern>
   </decorator>
   <decorator name="blog" page="blog-dec.jsp">
     <pattern>/blog.jsp
   </pattern></decorator>
   <decorator name="site" page="site-dec.jsp">
     <pattern>/*</pattern>
   </decorator>
</decorators>


V elementech můžeme krom názvů cest využívat také tzv. wildcards, tedy znaky se speciálním významem. Jedná se o znaky “?“, “*“, které zastupují po řadě jeden či více znaků. Toto mapování ConfigDecoratorMaper porovnává s hodnotou, kterou vrací metoda request.getServletPath().

Často se stává, že jedna vyhovuje více dekorátorům. Potom se jejich výběr řídí následujícími pravidly. Nejdříve se kontrolují vzory, které neobsahují wilcards a potom vzory, které je obsahují. Pokud toto porovnání selže, je vybrán ten dekorátor, jehož vzor je nejdelší, tedy vyhrává /blog/administrace/*.jsp nad /blog/*. Vyhrává tedy ten, jehož vzor obsahuje více lomítek “/“.

Obsah dekorátoru WEB-INF/site-dec.jsp



< %@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %>
<html>
   <head>
     <title><decorator :title default="MoroSystems | Programování v Javě" /></title>
     <meta http-equiv="content-type" content="text/html"; charset="utf-8">
     <decorator :head />
   </meta></head>
   <body>
     <h1>MoroSystems</h1>
     <div id="text">
        <decorator :body />
     </div>
   </body>
</html>


Pokud je nalezen správný dekorátor, který je JSP stránkou, Sitemesh pro něj vyšle požadavek. Tato stránka má přístup k rozpársované stránce, o které jsme se zmiňovaly v části o FastPageParseru. V dekorátoru můžeme použít knihovnu značek Sitemeshe k získání různých částí parsované stránky, jako jsou obsahy elementů title, head, body, které se vloží do vybraného dekorátoru. Takto zpracovaný dekorátor doplňen o části parsované stránky je vrácen prohlížeči jako obsah požadované stránky.

Příklad stránky site.jsp



< %@page language="java" contentType="text/html; charset=utf-8" pageEncoding="windows-1250" %>
<html>
   <head>
     <title>MoroSystems | Příklad - Sitemesh</title>
     <meta name="keywords" content="sitemesh" />
   </head>
   <body>
      <p>Stránka, která bude dekorována.</p>
   </body>
</html>

Výsledkem pak bude následující HTML kód



<pre><html>
  <head>
    <title>MoroSystems | Příklad - Sitemesh</title>
    <meta http-equiv="content-type" content="text/html"; charset="utf-8">
    <meta name="keywords" content="sitemesh" />
  </meta></head>
  <body>
    <h1>MoroSystems</h1>
    <div id="text">
      <p>Stránka, která bude dekorována.</p>
    </div>
  </body>
</html>


V přecházejícím textu jsme se seznámili s instalací a konfigurací aplikačního rámce Sitemesh a jeho použitím. Na závěr je však nutné poznamenat, že současná verze Sitemeshe, tedy verze 2.2.1, není vhodná pro použítí v aplikacích stavěných podle vzoru MVC, což by se ale mělo v příštích verzích změnit. Ale o tom snad někdy jindy v jednom z příštích dílů tohoto seriálu.

Relevantní odkazy