SiteMesh3文檔 http://wiki.sitemesh.org/wiki/pages/viewpage.action?pageId=1081348html
從新搭建項目偶然發現SiteMesh有了新版本SiteMesh3,本着用新不用舊原則果斷升級,多少遇了點坑,順便記錄下java
<dependency> <groupId>org.sitemesh</groupId> <artifactId>sitemesh</artifactId> <version>3.0.1</version> </dependency>
在web.xml中添加filterweb
<filter> <filter-name>sitemesh</filter-name> <filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class> </filter> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.ftl</url-pattern> </servlet-mapping>
添加配置文件 sitemesh3.xml
默認配置文件路徑爲:/WEB-INF/sitemesh3.xml app
<sitemesh> <!-- By default, SiteMesh will only intercept responses that set the Content-Type HTTP header to text/html This can be altered to allow SiteMesh to intercept responses for other types. 默認 SiteMesh 只對HTTP響應頭中Content-Type爲 text/html 的類型進行攔截和裝飾,若須要處理其它mime類型須要自行添加配置 --> <mime-type>text/html</mime-type> <!-- Map default decorator. This shall be applied to all paths if no other paths match. 配置裝飾器,僅設置decorator參數時表示爲默認的裝飾器,當沒有任何路徑被匹配時會使用默認裝飾器裝配 --> <mapping decorator="/WEB-INF/decorators/decorator.ftl"/> <!--對不一樣的路徑指定特定的裝飾器--> <!--<mapping path="/admin/*" decorator="/WEB-INF/decorators/admin-decorator.ftl"/>--> <!-- Alternative convention. This is more verbose but allows multiple decorators to be applied to a single path. 對同一路徑能夠同時使用多個裝飾器 --> <mapping> <path>/category/*</path> <decorator>/WEB-INF/decorators/common-decorator.ftl</decorator> <decorator>/WEB-INF/decorators/menu-decorator.ftl</decorator> <decorator>/WEB-INF/decorators/category-decorator.ftl</decorator> </mapping> <!-- Exclude path from decoration. 排除路徑,只需將exclue設置爲true便可 --> <mapping path="/static/*" exclue="true"/> <!-- An advanced feature of SiteMesh is the ability to define custom rules that manipulate tags on a page. These are classes that implement org.sitemesh.content.tagrules.TagRuleBundle. 默認SiteMesh僅支持title、head、meta、body等tag,能夠自定義tag,實現TagRuleBundle接口便可 --> <content-processor> <tag-rule-bundle class="com.sankuai.shangchao.util.HtmlTagRuleBundle"/> </content-processor> </sitemesh>
修改配置文件路徑
默認配置文件路徑爲:/WEB-INF/sitemesh3.xml 若須要修改配置文件路徑須要在filter裏配置configFile參數 框架
<filter> <filter-name>sitemesh</filter-name> <filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class> <init-param> <param-name>configFile</param-name> <param-value>/WEB-INF/sitemesh3.xml</param-value> </init-param> </filter>
自定義tagmaven
import org.sitemesh.SiteMeshContext; import org.sitemesh.content.ContentProperty; import org.sitemesh.content.tagrules.TagRuleBundle; import org.sitemesh.content.tagrules.html.ExportTagToContentRule; import org.sitemesh.tagprocessor.State; /** * Description: FootTagRuleBundle * Author: liuzhao * Create: 2015-08-22 09:21 */ public class HtmlTagRuleBundle implements TagRuleBundle { @Override public void install(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) { defaultState.addRule("foot", new ExportTagToContentRule(siteMeshContext, contentProperty.getChild("foot"), false)); } @Override public void cleanUp(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) { } }
decorator配置頁面佈局layout,對應的tag會被進行裝飾替換ide
<!DOCTYPE html>
<
html
>
<
head
>
<
title
>
<
sitemesh:write
property
=
"title"
/>
</
title
>
<
sitemesh:write
property
=
'head'
/>
</
head
>
<
body
>
<
h1
>啦拉拉,我是賣報的小行家</
h1
>
<
sitemesh:write
property
=
'body'
/>
<
sitemesh:write
property
=
"foot"
/>
</
body
>
</
html
>
|
sitemesh3是徹底獨立的,不和任何框架進行偶合,所以SpringMVC、FreeMarker配置徹底不須要考慮sitemesh3的兼容問題
在加載裝飾器的時候,會出現404問題,可能的緣由是找不到ftl文件的解析器,因此須要配置下ftl使用默認的Servlet解析,在web.xml中添加以下配置佈局
<servlet-mapping>
<servlet-name>
default
</servlet-name>
<url-pattern>*.ftl</url-pattern>
</servlet-mapping>
|
@Override
protected
boolean
postProcess(String contentType, CharBuffer buffer,
HttpServletRequest request, HttpServletResponse response,
ResponseMetaData metaData)
throws
IOException, ServletException {
WebAppContext context = createContext(contentType, request, response, metaData);
Content content = contentProcessor.build(buffer, context);
if
(content ==
null
) {
return
false
;
}
String[] decoratorPaths = decoratorSelector.selectDecoratorPaths(content, context);
//遍歷裝飾器進行裝飾
for
(String decoratorPath : decoratorPaths) {
content = context.decorate(decoratorPath, content);
}
if
(content ==
null
) {
return
false
;
}
try
{
content.getData().writeValueTo(response.getWriter());
}
catch
(IllegalStateException ise) {
// If getOutputStream() has already been called
content.getData().writeValueTo(
new
PrintStream(response.getOutputStream()));
}
return
true
;
}
public
Content decorate(String decoratorName, Content content)
throws
IOException {
if
(decoratorName ==
null
) {
return
null
;
}
class
CharBufferWriter
extends
CharArrayWriter {
public
CharBuffer toCharBuffer() {
return
CharBuffer.wrap(
this
.buf,
0
,
this
.count);
}
}
CharBufferWriter out =
new
CharBufferWriter();
decorate(decoratorName, content, out);
CharBuffer decorated = out.toCharBuffer();
Content lastContent = currentContent;
currentContent = content;
try
{
return
contentProcessor.build(decorated,
this
);
}
finally
{
currentContent = lastContent;
}
}
@Override
protected
void
decorate(String decoratorPath, Content content, Writer out)
throws
IOException {
HttpServletRequest filterableRequest =
new
HttpServletRequestFilterable(request);
// Wrap response so output gets buffered.
HttpServletResponseBuffer responseBuffer =
new
HttpServletResponseBuffer(response, metaData,
new
BasicSelector(
new
PathMapper<Boolean>(), includeErrorPages) {
@Override
public
boolean
shouldBufferForContentType(String contentType, String mimeType, String encoding) {
return
true
;
// We know we should buffer.
}
});
responseBuffer.setContentType(response.getContentType());
// Trigger buffering.
// It's possible that this is reentrant, so we need to take a copy
// of additional request attributes so we can restore them afterwards.
Object oldContent = request.getAttribute(CONTENT_KEY);
Object oldContext = request.getAttribute(CONTEXT_KEY);
request.setAttribute(CONTENT_KEY, content);
request.setAttribute(CONTEXT_KEY,
this
);
try
{
// Main dispatch.
dispatch(filterableRequest, responseBuffer, decoratorPath);
// Write out the buffered output.
CharBuffer buffer = responseBuffer.getBuffer();
out.append(buffer);
}
catch
(ServletException e) {
//noinspection ThrowableInstanceNeverThrown
throw
(IOException)
new
IOException(
"Could not dispatch to decorator"
).initCause(e);
}
finally
{
// Restore previous state.
request.setAttribute(CONTENT_KEY, oldContent);
request.setAttribute(CONTEXT_KEY, oldContext);
}
}
protected
void
dispatch(HttpServletRequest request, HttpServletResponse response, String path)
throws
ServletException, IOException {
//這裏調用加載文件會出現404錯誤 /WEB-INF/decorators/decorator.ftl
RequestDispatcher dispatcher = servletContext.getRequestDispatcher(path);
if
(dispatcher ==
null
) {
throw
new
ServletException(
"Not found: "
+ path);
}
dispatcher.forward(request, response);
}
|