sitemesh的script提取
声明:本文转载自https://my.oschina.net/qixiaobo025/blog/1593655,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。
背景
前文交代了一些使用sitemesh的背景土鳖的jsp改造
那么本着怎么简单怎么来的原则首先创建了一个通用模板
实现
-
修改pom文件引入sitemesh
<dependency> <groupId>org.sitemesh</groupId> <artifactId>sitemesh</artifactId> <version>3.0.1</version> </dependency>
-
修改webxml增加对应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>
-
新建sitemesh3.xml
<sitemesh> <!-- 默认的装饰路径。如果没有配置其他的路径将启用默认路径,这个可以适用于所有路径 --> <!-- Map default decorator. This shall be applied to all paths if no other paths match. --> <mapping decorator="/WEB-INF/sitemesh/main.jsp"/> <!-- 配置 不被装饰 的路径 --> <!-- Exclude path from decoration. --> <mapping path="/login/**" exclue="true"/> <!-- 默认情况下, sitemesh 只对 HTTP 响应头中 Content-Type 为 text/html 的类型进行拦截和装饰, 我们也可以添加更多的 mime 类型 --> <mime-type>text/html</mime-type> <mime-type>application/vnd.wap.xhtml+xml</mime-type> <mime-type>application/xhtml+xml</mime-type> <!-- Sitemesh 3 默认只提供了 body,title,head 种 tag 类型 我们可以添加自定义的tag规则 --> </sitemesh>
-
我们除了登录之外的所有html页面进行装饰
-
定义模板文件
<%@ page contentType="text/html; charset=utf-8" %> <%@ page language="java" pageEncoding="UTF-8" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title> <sitemesh:write property='title'/> </title> <sitemesh:write property='head'/> </head> <body class="mainBody"> <sitemesh:write property='body'/> </body> </html>
-
这样很轻易就定义了一套模板
- 我们的目的是将script下沉到body的结尾 因此考虑增加scipt的提取
-
在sitemesh3.xml定义如下
<content-processor> <tag-rule-bundle class="com.air.tqb.decorator.ScriptTagRuleBundle"/> </content-processor>
-
新建sciptTag
/** * @author qixiaobo */ public class ScriptTagRuleBundle implements TagRuleBundle { private static final String TAG_SCRIPT = "script"; @Override public void install(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) { defaultState.addRule(TAG_SCRIPT, new ExportTagToContentRule(siteMeshContext, contentProperty.getChild(TAG_SCRIPT), false)); } @Override public void cleanUp(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) { } }
-
修改main.jsp为
<%@ page contentType="text/html; charset=utf-8" %> <%@ page language="java" pageEncoding="UTF-8" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title> <sitemesh:write property='title'/> </title> <sitemesh:write property='head'/> </head> <body class="mainBody"> <sitemesh:write property='body'/> <sitemesh:write property='script'/> </body> </html>
-
不过考虑可能存在一些问题 scipt提取出来 那么其中的一些src要复写等等 还比较麻烦
- 重启服务后结果大失所望 script并没有被提取
- 检索发现也有国外小伙伴和我的思路一样 https://stackoverflow.com/questions/1914381/is-it-possible-to-extract-script-tags-using-sitemesh 【不过已经是8年前的啦 当时还是sitemesh2吧】
- 考虑一下为啥script并没有被识别成tag呢?
-
查看源码后发现 sitemesh将script标签识别成
<YYINITIAL> { "<!--" [^\[] ~"-->" { return TagTokenizer.Token.TEXT; } /* All comments unless they start with <!--[ */ "<!---->" { return TagTokenizer.Token.TEXT; } "<?" ~"?>" { return TagTokenizer.Token.TEXT; } "<!" [^\[\-] ~">" { return TagTokenizer.Token.TEXT; } "<![CDATA[" ~"]]>" { return TagTokenizer.Token.TEXT; } "<xmp" ~"</xmp" ~">" { return TagTokenizer.Token.TEXT; } "<script" ~"</script" ~">" { return TagTokenizer.Token.TEXT; } [^<]+ { return TagTokenizer.Token.TEXT; } "<" { yybegin(ELEMENT); return TagTokenizer.Token.LT; } "<!--[" { yybegin(ELEMENT); return TagTokenizer.Token.LT_OPEN_MAGIC_COMMENT; } "<![" { yybegin(ELEMENT); return TagTokenizer.Token.LT_CLOSE_MAGIC_COMMENT; } }
-
原来sitemesh不能支持script标签啊!
- 似乎走到了绝路
- 不过假设真的支持script 那么一些属性的设置也很麻烦啊 比如src 比如async等等
- 灵光一闪 既然script不支持 那么我们可以仿照jsp定义自己的标签啊!
- 定义f6scriprt标签 该标签表示f6script中的数据将会移到body的末尾
- 那么思路豁然开朗 我们将之前reference中的一些js拆分 【jQuery等依然可以放在前面加载 大部分js依赖】非必须js 比如百度统计 比如客服js等等我们放在f6script块中
-
改造scriptTag
package com.air.tqb.decorator; 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; /** * @author qixiaobo */ public class ScriptTagRuleBundle implements TagRuleBundle { private static final String TAG_SCRIPT = "f6script"; @Override public void install(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) { defaultState.addRule(TAG_SCRIPT, new ExportTagToContentRule(siteMeshContext, contentProperty.getChild(TAG_SCRIPT), false)); } @Override public void cleanUp(State defaultState, ContentProperty contentProperty, SiteMeshContext siteMeshContext) { } }
-
修改模板文件为
<%@ page contentType="text/html; charset=utf-8" %> <%@ page language="java" pageEncoding="UTF-8" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title> <sitemesh:write property='title'/> </title> <sitemesh:write property='head'/> </head> <body class="mainBody"> <sitemesh:write property='body'/> <sitemesh:write property='f6script'/> </body> </html>
-
在需要包装到结尾的js做如下处理 使用<f6script></f6script>进行包装
- js会乖乖的跑到了body结束符前
-
抱拳了,老铁!
本文发表于2017年12月22日 20:32
(c)注:本文转载自https://my.oschina.net/qixiaobo025/blog/1593655,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.
阅读 2210 讨论 0 喜欢 0