文档章节

sitemesh3 源码分析

韭菜根
 韭菜根
发布于 2012/03/09 12:51
字数 1225
阅读 1823
收藏 6

sitemesh3是一个页面布局框架,可以是你的页面无缝的嵌入到一个整体页面中,从而是你的页面看起来风格是一致的,所有的一切从这里开始

ConfigurableSiteMeshFilter

public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
configProperties = getConfigProperties(filterConfig);
autoReload = getAutoReload();
logger.config("Auto reloading " + (autoReload ? "enabled" : "disabled"));

synchronized (configLock) {
deployNewFilter(setup());
}
initialized = true;
}

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if (!initialized) {
throw new ServletException(getClass().getName() + ".init(FilterConfig) was not called");
}
reloadIfNecessary();
filter.doFilter(servletRequest, servletResponse, filterChain);
}

sitemesh3是从该filter开始的,首先看init(),了解它初始化过程

我们看到configProperties = getConfigProperties(filterConfig);,是filter的配置信息,autoReload = getAutoReload();  查看配置文件是否需要自动重加载,默认是开启的。从后边可以知道它是通过对比sitemesh3.xml的最后修改时间来确定是不是需要加载的

这些只是准备工作,关键点在 deployNewFilter(setup()); ,也就是setup方法中

setup会创建一个filter,当执行到doFilter() ,内部实际执行的就是filter.doFilter(),到这里就可以肯定所有核心内容都在这个filter中,包括init和filter的过程,首先我们看init的过程,了解它都需要那些东西,然后再看doFilter中的内容,来决定我们怎么改进它。

protected Filter setup() throws ServletException {
ObjectFactory objectFactory = getObjectFactory();
SiteMeshFilterBuilder builder = new SiteMeshFilterBuilder();

new PropertiesFilterConfigurator(objectFactory, configProperties)
.configureFilter(builder);

new XmlFilterConfigurator(getObjectFactory(),
loadConfigXml(filterConfig, getConfigFileName()))
.configureFilter(builder);

applyCustomConfiguration(builder);

return builder.create();
}

一行一行的来讲ObjectFactory里面其实只有一行代码 return class.forName(className) ,就是为类生成对象,同时隔离到那些exception。

builder 这个类很重要,所有的配置信息都会存到里面,PropertiesFilterConfigurator 这行是将web.xml 中sitemeshfilter中的配置信息,存放到builder中

下面一行是将sitemesh3.xml中的配置信息,存放到builder中。

applyCustomConfiguration(builder);这行是为了通过java编码的方式来配置filter

配置信息有 exclude, decorate, minetype,content-processor,tag-rule-bundle

exclude 是不需要装饰,decorate是需要装饰的, minetype 是默认返回的页面类型, content-processor 是自定义的页面内容处理器,tag-rule-bundle 是自定义的标签,如<sitemesh:write/>等。

这里就可以看清楚sitemesh配置有三种方式 1,filter,2,sitemesh.xml, 3 java硬编码 ,混合使用的话,优先级从搞到低

下面我们去详细看看builder中有什么东西

Filter create() {
return new SiteMeshFilter(
getSelector(),
getContentProcessor(),
getDecoratorSelector());
}

看到没有一个热乎的filter出炉了, 用到了builder的三个属性, selector 选择器,contentProcessor 内容处理器,decoratorSelector 装饰选择器
我们继续深入:selector 是关于mineType决定是否拦截 , contentProcessor 是解析标签的 ,decoratorSelector 是关于装饰页面和被装饰页面的关系

好了,初始化过程基本就看完了,接下来就到正餐时间了,从上面我们没有看到更多的默认配置信息, 下一步就是这里filter.doFilter() ,等把这个过程理完了,然后再把代码通读一遍就能明白了

SiteMeshFilter.class
FilterConfig filterConfig = getFilterConfig();
if (filterConfig == null) {
// TODO: Is this really necessary? Can we survive without init() being called?
throw new ServletException(getClass().getName() + ".init() has not been called.");
}

HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
ServletContext servletContext = filterConfig.getServletContext();

if (!selector.shouldBufferForRequest(request)) {
// Optimization: If the content doesn't need to be buffered,
// skip the rest of this filter.
filterChain.doFilter(request, response);
return;
}

if (containerTweaks.shouldAutoCreateSession()) {
// Some containers (such as Tomcat 4) will not allow sessions
// to be created in the decorator. (i.e after the
// response has been committed).
request.getSession(true);
}

try {

// The main work.
bufferAndPostProcess(filterChain, request, response, selector);

} catch (IllegalStateException e) {
// Some containers (such as WebLogic) throw an IllegalStateException when an error page is served.
// It may be ok to ignore this. However, for safety it is propegated if possible.
if (!containerTweaks.shouldIgnoreIllegalStateExceptionOnErrorPage()) {
throw e;
}
} catch (RuntimeException e) {
if (containerTweaks.shouldLogUnhandledExceptions()) {
// Some containers (such as Tomcat 4) swallow RuntimeExceptions in filters.
servletContext.log("Unhandled exception occurred whilst decorating page", e);
}
throw e;
}

FilterConfig filterConfig = getFilterConfig(); 还记得这是什么时候注入的吗
!selector.shouldBufferForRequest(request) 初步判断: 是否已经呗sitemesh filter拦截过了, 是否不需要装饰
if (containerTweaks.shouldAutoCreateSession()) { 是否返回false, 是为适应tomcat4 写的
接下来看 关键部分 bufferAndPostProcess ,前面几行可以不用看 关键在于:

。。。。
filterChain.doFilter(wrapRequest(request), responseBuffer);
CharBuffer buffer = responseBuffer.getBuffer();

// If content was buffered, post-process it.
boolean processed = false;
if (buffer != null && !responseBuffer.bufferingWasDisabled()) {
processed = postProcess(responseBuffer.getContentType(), buffer, request, response, metaData);
}

if (!response.isCommitted()) {
responseBuffer.preCommit();
}

// If no decoratoes applied, and we have some buffered content, write the original.
if (buffer != null && !processed) {
writeOriginal(response, buffer, responseBuffer);
}

省略的几行是封装response,以便得到返回的html内容,还有就是控制response 的状态 如 if_modified_since 等
buffer是 返回的页面内容,已经被web容器解析过了。
在postProcess 开始进行装饰,如果没有成功就就buffer直接写入到response中
看postProcess 方法:

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;
}

content.getData().writeValueTo(response.getWriter());
return true;

首先用rule规则将内容解析一遍,再找到要装饰的页面,然后用dispatch去解析,取得内容后,用context将被装饰页面和装饰页面一起解析
接下来我们着重看看一下 contentProccesor.build() 和 context.decorate() 和 context.build() 即可

就先到这里吧,自己一边看一边写挺累的

© 著作权归作者所有

共有 人打赏支持
韭菜根

韭菜根

粉丝 72
博文 27
码字总数 12032
作品 1
海淀
程序员
私信 提问
加载中

评论(2)

hemingwang0902
hemingwang0902
分析得比较深入,很有参考价值
Hartwell
Hartwell
很不错,参考了!
SpringMVC整合sitemesh3后无法POST

从新整理一下: 问题描述: SpringMVC中有一个方法被定义为 method= RequestMethod.POST, 详细代码如下 配置完后用一页面测试请求,代码如下 一切完美运行,没有任何错误 现在引入sitemesh3...

Nesson
2013/04/10
3.4K
2
sitemesh3 但输出的html总是被截断,不知道是否为content-length问题,求助高手?

各位大牛,我用的sitemesh3 + springmvc + mybatis + shiro,按官方3.0配置可执行,但输出的页面中body中的内容总是只输出一部分就截断了,不知道是否是sitemesh3源码中对content-length计算...

binux
2016/06/28
780
4
让Sitemesh3支持渲染错误页面

Sitemesh 3 一直让我蛮困扰的是不能把那些error页面也给渲染到框架页中,查询源码发现是在 org.sitemesh.webapp.contentfilter.BasicSelector.BasicSelector(boolean, String...) 这个类里面...

郁也风
2013/05/17
0
0
求职:JAVA高级开发或者J2EE开发

转眼都工作两年了,回首这两年貌似在公司也没学到多少东西。下面简单说说自己的一些情况吧。 刚从学校毕业时自己只会s2sh,幸运的找到了一家做B2B的公司做J2EE开发,在这个公司开始使用ssh,并...

论韭菜的100种吃法
2012/05/15
1K
19
关于 sitemesh3 性能问题

谁做过sitemesh3的性能测试。sitemesh3性能怎么样?大家都用哪个布局页面的?

Mr.CT
2012/02/06
5.1K
6

没有更多内容

加载失败,请刷新页面

加载更多

《傲慢与偏见》的读书笔记与读后感作文2400字

《傲慢与偏见》的读书笔记与读后感作文2400字: 作者:孙苑馨;笔者按:读书这个习惯是我爸妈养出来的。小时候父母赚的钱除了吃饭穿衣剩下的就是买书了,他们除了买各种新鲜出版的文艺派图书...

原创小博客
7分钟前
0
0
oozie job 的挂了监控报警或重启

oozie Coordinator 的job 和actioni状态很多,但好像不支持设置某状态如failed后30分钟后自动重新拉启,因他的条件只有几种:触发条件可以是一个时间频率、一个dataset实例是否可用,或者可能...

hblt-j
26分钟前
1
0
python精简笔记-[6]-条件判断[if]语句

语法: if 判断条件: 执行语句……elif 判断条件:    执行语句……elif 判断条件:    执行语句……else: 执行语句…… 实例1: n = input("请输入您的性别: "...

平头哥-Enjoystudy
29分钟前
0
0
RxJava 是如何实现线程切换的(上)

前言 通过前一篇的从观察者模式出发,聊聊RxJava,我们大致理解了RxJava的实现原理,在RxJava中可以非常方便的实现不同线程间的切换。subscribeOn 用于指定上游线程,observeOn 用于指定下游线...

亭子happy
56分钟前
2
0
想晋级高级工程师只知道表面是不够的!Git内部原理介绍

本文由云+社区发表 作者:腾讯工蜂用户:王二卫 从不一样的视角了解git,以便更好的使用git 一、git & git 版本库认识 git 是一个内容寻址的文件系统,其核心部分是一个简单的键值对数据库(...

腾讯云加社区
59分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部