I've always like
Sitemesh even those days before I was introduced to WebWork. I guess after that I just like it even more. Funny thing is not much people seems to be using Sitemesh out there though. Guess more people are familiar with Tiles thanks to Struts I guess.
This is what i know about Sitemesh and what works for me when setting up Sitemesh
#1 Declare sitemesh filters in web.xml
<web ...="...">
<filter>
<filter-name>sitemesh
<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter
</filter>
...
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*/<url-pattern>
</filter-mapping>
</web>
# 2 add sitemesh.xml and decorator.xml in '/WEB-INF/' directory
sitemesh.xml by default exists in sitemesh jar file and the copy in sitemesh jar file will be used if one cannot be found in /WEB-INF directory. It's really useful to have a custimizable copy of sitemesh.xml lying in your /WEB-INF directory so you can tweak and perhaps add custom parsers, mappers etc. Following is a copy of a typical sitemesh.xml file
<sitemesh>
<property name="decorators-file" value="/WEB-INF/decorators.xml">
<excludes file="${decorators-file}">
<page-parsers>
<parser class="com.opensymphony.module.sitemesh.parser.HTMLPageParser" content-type="text/html">
</parser>
</page-parsers>
<decorator-mappers>
<mapper class="com.opensymphony.module.sitemesh.mapper.PageDecoratorMapper">
<param name="property.1" value="meta.decorator" />
<param name="property.2" value="decorator" />
</mapper>
<mapper class="com.opensymphony.module.sitemesh.mapper.FrameSetDecoratorMapper">
<mapper class="com.opensymphony.module.sitemesh.mapper.PrintableDecoratorMapper">
<param name="decorator" value="printable" />
<param name="parameter.name" value="printable" />
<param name="parameter.value" value="true" />
</mapper>
<mapper class="com.opensymphony.module.sitemesh.mapper.FileDecoratorMapper">
<mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper">
<param name="config" value="${decorators-file}" />
</mapper>
</decorator-mappers>
</sitemesh>
Couple of important things :-
Parsers
These are sitemesh parser parsing html into sitemesh internal Page object to be used by mappers, decorators etc., we'd rarely need to ever change this
<property> tag
These are tags so you can later refer to the property value through ${...} syntax.
<excludes> tag
Exclude files from being parsed, we wanna exclude ${decorator-file} which points to /WEB-INF/decoratorsx.ml cause we have a mapper that specifically parse this file later.
<mapper> tag
mappers map an incoming request to a decorator which decorates in incoming request and producing a decorated request ultimately returned to the browser. They are executed in order and
ConfigDecoratorMapper
should always be the last cause it is a 'catch all' mapper.
Following is a typical copy of
decorators.xml
<decorators>
<excludes>
<pattern>/bootstrap/*
</excludes>
<decorator name="error_page" page="/WEB-INF/decorators/error_page_layout.jsp">
<pattern>/error.do
</decorator>
...
<decorator name="information_panel" page="/WEB-INF/decorators/information_panel_layout.jsp">
</decorator>
</decorators>
With the above example
- '/bootstrap/*' will not be decorated
- '/error.do' will be decorated by '/WEB-INF/decorators/error_page_layout.jsp'
In the layout jsp, we could use the following tags :-
<%@taglib prefix="sitemesh-decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %>
<%@taglib prefix="sitemesh-page" uri="http://www.opensymphony.com/sitemesh/page" %>
<sitemesh-decorator:title />
<sitemesh-decorator:head />
<sitemesh-decorator:body />
<sitemesh-decorator:getProperty property="..." default="[default value if no property found]" writeEntireProperty="[yes/no]" />
<sitemesh-decorator:usePage id="..." />
<sitemesh-page:applyDecorator name="..." title="..." page="..."/>
<sitemesh-decorator:title/> tag
Get the content inside html <title> tag of our original html page
<sitemesh-decorator:head/> tag
Stick in the <head> tag content of our original html page, only the content not the enclosing tags though.
<sitemesh-decorator:body/> tag
Stick in the <body> content of our original html page, everything in it.
<sitemesh-decorator:usePage id="..." />
Stick sitemesh Page object into request scope under the variable name given by 'id' attribute.
<sitemesh-page:applyDecorator page="..."/>
Apply the decorator given by 'page' attribute against the body of this tag. In other words, the body of this tag is going to be decorated by the decorator given in page attribute.
<!--
Apply decorator named 'myDecorator' on the body of this tag.
-->
<sitemesh-page:applydecorator name="myDecorator">
...
</sitemesh-page:applydecorator>
<!--
Apply decorator located at '/WEB-INF/decorators/myDecorator' on the body
of this tag overriding the title (if exists) in the body of this tag.
-->
<sitemesh-page:applydecorator page="/WEB-INF/decorators/myDecorator" title="...">
...
</sitemesh-page:applydecorator>
<sitemesh-decorator:getProperty /> tag
Stick in the parsed original html page's bits and pieces Eg.
<html> tag attributes are sticked in as properties without any prefix
<title> tag content are sticked in as 'title'
<body> tag attributes are sticked in with prefix 'body'
<meta> tag 'content' attributes content are sticed in with prefix 'meta'
Eg.
with :-
<html myAttribute="test">
<head>
<title>my title</title>
<meta name="meta-name" content="meta-content" />
</head>
<body onload="alert('ready');">
</body>
</html>
<!--
This will gives us "test" from tag's attribute
-->
<sitemesh-decorator:getProperty property="myAttribute" />
<!--
This will gives us 'my title' from the content of <title> tag
-->
<sitemesh-decorator:getProperty property="title" />
<!--
This will gives us 'meta-content' from tag with name 'meta-name'
-->
<sitemesh-decorator:getProperty property="meta.meta-name" />
<!--
This will gives us 'alert('ready');' from onload attribute in <body> tag
-->
<sitemesh-decorator:getProperty property="body.onload" />
Chao ^_^