标签:
SiteMesh3文档 http://wiki.sitemesh.org/wiki/pages/viewpage.action?pageId=1081348
重新搭建项目偶然发现SiteMesh有了新版本SiteMesh3,本着用新不用旧原则果断升级,多少遇了点坑,顺便记录下
<dependency> <groupId>org.sitemesh</groupId> <artifactId>sitemesh</artifactId> <version> 3.0 . 1 </version> </dependency> |
在web.xml中添加filter
<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
< 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> |
自定义tag
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会被进行装饰替换
<!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); } |
SiteMesh3整合SpringMVC+FreeMarker
标签:
原文地址:http://www.cnblogs.com/lzrabbit/p/5176992.html