sitemesh的script提取


title: sitemesh的script提取 tags:

  • sitemesh
  • jsp
  • template
  • script categories: 工作日志 date: 2017-12-23 10:50:38

背景

前文交代了一些使用sitemesh的背景土鳖的jsp改造

那么本着怎么简单怎么来的原则首先创建了一个通用模板

 

实现

  1. 修改pom文件引入sitemesh
        <dependency>
            <groupId>org.sitemesh</groupId>
            <artifactId>sitemesh</artifactId>
            <version>3.0.1</version>
        </dependency>
复制代码
 
复制代码
  1. 修改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>
复制代码
 
复制代码
  1. 新建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>
复制代码
  1. 我们除了登录之外的所有html页面进行装饰
  2. 定义模板文件
        <%@ 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>
复制代码
  1. 这样很轻易就定义了一套模板
  2. 我们的目的是将script下沉到body的结尾 因此考虑增加scipt的提取
  3. 在sitemesh3.xml定义如下
        <content-processor>
            <tag-rule-bundle class="com.air.tqb.decorator.ScriptTagRuleBundle"/>
        </content-processor>
复制代码
 
复制代码
  1. 新建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) {
         
            }
        }
复制代码
  1. 修改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>
复制代码
 
复制代码
  1. 不过考虑可能存在一些问题 scipt提取出来 那么其中的一些src要复写等等 还比较麻烦
  2. 重启服务后结果大失所望 script并没有被提取
  3. 检索发现也有国外小伙伴和我的思路一样 stackoverflow.com/questions/1… 【不过已经是8年前的啦 当时还是sitemesh2吧】
  4. 考虑一下为啥script并没有被识别成tag呢?
  5. 查看源码后发现 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; }
        }
复制代码
  1. 原来sitemesh不能支持script标签啊!
  2. 似乎走到了绝路
  3. 不过假设真的支持script 那么一些属性的设置也很麻烦啊 比如src 比如async等等
  4. 灵光一闪 既然script不支持 那么我们可以仿照jsp定义自己的标签啊!
  5. 定义f6scriprt标签 该标签表示f6script中的数据将会移到body的末尾
  6. 那么思路豁然开朗 我们将之前reference中的一些js拆分 【jQuery等依然可以放在前面加载 大部分js依赖】非必须js 比如百度统计 比如客服js等等我们放在f6script块中
  7. 改造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) {
         
            }
        }
复制代码
  1. 修改模板文件为
        <%@ 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>
复制代码
 
复制代码
  1. 在需要包装到结尾的js做如下处理 使用进行包装
  2. js会乖乖的跑到了body结束符前
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值