zoukankan      html  css  js  c++  java
  • 转: Apache SSI详解及应用

    转: Apache SSI详解及应用

    什么是 SSI?

    SSI(Server Side Includes),是嵌套在 HTML 网页中的指示语句,由后台服务器进行代码的解释计算。使用 SSI 可以动态的创建一部分网页内容而不需要编写复杂的 JSP/ASP/PHP 等程序。SSI 是如此的小巧以至于不应算作一门语言,因为他远没有JSP/ASP/PHP 等程序那么复杂,只有一些极其有限的语法规则。

    很多 HTTP Server 程序都支持 SSI,可能语法稍有不同,比如: IIS/Novell HTTP Server 等等,大同小异,本文要说明的是 Apache 2.0 的 SSI。闲话少说,我想告诉大家的是,这是一篇实践经验总结性的文章,后文中的示例解决方案都是来自实际的网站应用中。

    开启SSI功能需先对apache配置文件(httpd.conf)进行设置 详情请百度

    <Directory "D:/myProject/web">
    AddType text/html .ssi    #这里可以是 .shtml 或其他 不一定要 .ssi, 设置.ssi后缀的也是text/html类型的文件
    Options Includes
    AddOutputFilterByType INCLUDES; DEFLATE text/html  #输出处理器
    </Directory>
    

    测试SSI是否成功启用 编辑文件

    //  test.ssi :
    # echo指令输出变量 DATE_LOCAL
    <!--#echo var="DATE_LOCAL" -->
    ## 特别注意 <!--# 之间不能有任何空格,不然指令是无效的,被当作html注释
    

    **因为很多IDE都有注释代码行的快捷键, 如 sublime text( ctrl + /) 但是会变成 <!-- #echo var="..." -->,由于多了个空格,所以ssi指令被当成注释了。 **

    浏览器访问 http://localhost/test.ssi 能看到打印当前时间 说明SSI已启用


    关于SSI的更多参考资料

    这些文档也可以在 Apache的安装文件夹找到:
    Apache Tutorial: Introduction to Server Side Includes
    Apache mod_include

    SSI语法:

    <!--#fn attribute=value attribute=value ... --> fn可以理解成函数或者指令。 例子:

    #环境变量习惯大写
    http://<!--#echo var="SERVER_NAME" var="DOCUMENT_URI"-->  
    
    #virtual的值可以是相对路径或绝对路径 如 virtual="/ssi/footer.ssi" 
    <!--#include virtual="ssi/footer.ssi" --> 
    
    #file的值只能是相对路径
    <!--#include file="footer.ssi" --> 
    
    #设置自定义变量
    <!--#set var="protocol" value="http" --> 
    

    SSI 语句是直接嵌套在 HTML 页面中的,可以放置在任意的位置。所以 SSI 语句前后采用 HTML 注释的写法,这样一旦服务器关闭了对 SSI 的支持,此时访问页面的话,也不会直接在网页上显示出不必要的代码。

    SSI不区分大小写,环境变量用大写是很好的习惯;
    SSI中只有一种数据类型:字符串;
    SSI中的转义符是 ,字符串可以用双引号或单引号包裹 ,同JS

    SSI 中的变量分为自定义变量和环境变量**

    自定义变量使用 set 命令来创建:<!--#set var="protocol" value="http" -->
    环境变量是系统已经存在的一些默认的变量和变量值,可以直接使用。 <!--#echo var=”DATE_LOCAL” -->
    DATE_LOCAL 就是一个环境变量,用来显示当前本地时间。类似的环境变量还有很多,比如常用HTTP_HOST、SERVER_NAME、DOCUMENT_URI、DOCUMENT_NAME 等等。

    # 查看所有环境变量
    # 由于无换行所以按ctrl+u,以网页源代码的方式查看更清晰点
    <!--#printenv--> 
    
    # ------- 应用示例: --------------
    <body>
        <!--#include virtual="/bnn/ssi/header.ssi"-->
        <div id="Main">
            <div id="Content">
                <p>This is "<a href="http://<!--#echo var='SERVER_NAME' -->">Learning Apache SSI</a>" testing page!</p>
                <p>Hello SSI</p>
                <p>Today is: <!--#echo var="DATE_LOCAL" --></p>
            </div>
        </div>
        <!--#include virtual="ssi/footer.ssi"-->
        </body>
    

    数据类型:SSI 中只有一种数据类型“字符串”。例如:

    <!--#set var=”MyFirstVar” value=”120” -->
    <!--#set var=”MySecondVar” value=”20” -->
    # $MyFirstVar < $MySecondVar  //因为2个变量都是字符串值 所以执行的是字符串比较(比较每个字符的ASCII码大小)
    

    SSI常用指令

    SSI 的元素并不多,下面列出常用的元素和属性,其它请查看官方参考。

    echo :将变量值写入 HTML 代码中。

    #可以一次输出多个变量值 
    <!--#echo var="DATE_LOCAL"--> 
    http://<!--#echo var=”SERVER_NAME” var=”DOCUMENT_URI” -->
    

    include :在语句所在位置引入子页面。

    include 是 SSI 中最常用的命令,也是 SSI 主要功能的体现。

    # virtual的值可以是相对路径或绝对路径, 但注意路径中不能包含主机名;
    #路径可以是相对当前文件(SSI 语句所在的页面)或者从“/”开始,相对网站根目录的路径;
    <!--#include virtual="ssi/header.ssi"--> 
    # 路径后允许加参数
    <!--#include virtual="/cgi-bin/ap/optin_cn.pl?btn=send&fax=yes" --> 
    

    SSI 是允许嵌套的;例如,假设有三个文件,file1 include file2,file2中 include file3。

    set :创建变量或修改变量值

    <!--#set var=”Protocol” value=”http” -->
    # 若变量值带引号,可以这样:
    <!--#set var="MyVar1" value='"IBM"' -->  //value的值可以是字符串常量或者变量 如:value="$MyVar2" 
    <!--#set var="MyVar2" value=""IBM"" -->
    

    SSI中的变量都带$前缀 如:$Myvar,为了更清晰的表达一个变量 通常用大括号把变量名包起来 ${MyVar} , 同php

    <!--#set var="MyVar1" value="IBM" -->
    <!--#set var="MyVar2" value="Services" -->
    <!--#set var="MyVar3" value="${MyVar1}${MyVar2}" -->  //设置 MyVar3 = MyVar1+MyVar2
    <!--#echo var="MyVar3" -->
    
    <!--#set var="MyVar3" value="abc${MyVar1}_${MyVar1}def" --> // 修改MyVar3的值
    <!--#echo var="MyVar3" -->
    
    <!--#set var=”MyVar1” value=”IBM” -->
    <!--#set var=”MyVar2” value=”$MyVar1” --> // 变量值为 "$IBM"
    
    # 另一个把变量写在 SSI 语句中的例子:
    <!--#include virtual="/servers/eserver/${cc}/ssi/nav_left.ssi" -->  // 这个比较有用。
    

    fsize 和flastmod

    显示指定文件的大小(fsize)和指定文件的最后修改时间(flastmod)

    virtual – 与元素 include 中的属性相同,<!--#fsize virtual=”/cgi-bin/cmail.pl” --> 结果返回的是这个 Perl 脚本文件的大小,而不是运行这段 Perl 脚本的结果。

    SSI 配置元素

    • config指令
      配置一些 SSI 运行结果;错误信息、文件大小格式、时间格式。
      errmsg属性 当 SSI 语句运行出错时显示的信息。 例如:<!--#config errmsg="出错啦# " -->
      sizefmt 显示以何种方式显示文件大小。这个属性有两个值:bytes 和 abbrev。

        <!--#config sizefmt="bytes" -->  //按bytes大小显示
        <!--#config sizefmt="abbrev" --> //按bytes、Kb或Mb动态显示 视文件大小
      

      timefmt 显示时间的格式。属性值的参数同 C 标准库中的strftime(3) 相同;

        <!--#config timefmt="%Y-%m-%d"-->
        <!--#config timefmt="%Y-%m-%d"-->
        <meta name="DC.DATE" scheme="iso8610" content="<!--#echo var=’LAST_MODIFIED’-->">
      

    流控制元素

    条件语句

    SSI 中只有条件语句一种结构,而且结构很简单。基本的控制元素:

    <!--#if expr="test_condition"-->
        html or SSI statements
    <!--#elif expr="test_condition"-->
        html or SSI statements
    <!--#else-->
        html or SSI statements
    <!--#endif-->
    ## if 语句可以嵌套,你可以在 if 块中再加入一个 if 块语句。
    

    非空字符串为真,空串为假

    <!--#if expr="IBM" -->  // 表示条件成立;
    <!--#if expr="" -->  //空字符,返回 假,条件不成立。
    

    判断一个变量是否为空字符串的一种写法:<!--#if expr="$MyVar = ‘’" -->

    比较运算符 = != < <= > >=

    <!--#if expr="$DOCUMENT_URI = ‘/bnn/index.html’" -->
    codes
    <!--#endif -->
    

    逻辑运算符 ! && || 同JS

    运算符优先级 比较运算符优先级高于逻辑运算符 ; && 和 || 具有相同的优先级,可以使用括号 () 进行分组。

    <!--#if expr="$a = test1 && $b = test2" -->
    <!--#if expr="($a = test1) && ($b = test2)" -->
    

    任何不被识别为变量或者操作符都被当作是一个字符串。字符串也可以使用引号(单引号或者双引号)括起来。不被引号括起来的字符串中不允许有空格或者 Tab,因为空格是被用来起到分隔的作用。如果一个字符串中包含空格,请使用引号括起来。

    <!--#if expr="$a = test1 && $b = ‘test 2’" -->
    

    正则表达式

    Regular expression (正则表达式,缩写 RE),是一种对字符串进行匹配查找的高效模式。几乎每一种语言都支持 RE;Apache SSI 中的 RE 语法同 Perl(版本 5)语言中的相同,但并不完整的支持

    <!--#if expr="$QUERY_STRING = /^sid=([a-zA-Z0-9]+)/" -->
        <!--#set var="session" value="$1" -->
    <!--#endif -->
    

    说明:此例表示从参数中提取子字符串。$QUERY_STRING 是环境变量,表示通过网页 URL 传递过来的参数,例如:
    http://www.IBM.com/index.html?sid=safsaf43513sadfz&cntry=cn 其中,问号后面的部分就是 $QUERY_STRING 的值。

    如果等号右边的比较部分是 / / 这种形式,则表示,这部分是正则表达式

    /^sid=([a-zA-Z0-9]+)/ 括号表示分组,用圆括号分组的同时,程序自动会将圆括号内匹配的部分提取出来保存在 $1 这个变量中;这个 $1 是系统变量,用来保存正则表达式分组提取出来的各个部分值,一共有 9个,$1-$9。

    SSI 与 JavaScript

    SSI 与 JS 如何一起使用呢?是这样的,由于服务器并不能识别 JS 代码,所以可以把 SSI 语句放到 JS 代码行中,这样取代一部分 JS 代码的工作,将这部分工作放到服务器端运行。

    <!--#if expr="$DOCUMENT_URI = //bnn//" -->  //正则匹配 形如:/bnn/ 的路径,然后设置变量 SSI变量在JS中输出
        <!--#set var="LASLink" value="http://localhost/bnn/" -->
        <!--#set var="LASText" value="Learning Apache SSI" -->
    <!--#endif -->
    
    <script type="text/javascript">
    //<![CDATA[
        document.write(‘<a class="fbox" href="<!--#echo var="LASLink" -->"><!--#echo var="LASText" --></a>’);
    //]]>
    </script>
    

    SSI 与 日期

    前几天遇到这样一个需求:一个 Promotion - 3月3日之前显示默认的内容,3月3日之后显示另外一个内容。下面给出这段代码,分享一下类似这种的要求该如何入手。

    <!--#config timefmt="%Y-%m-%d"--> # 配置日期格式
    <!--#if expr="$DATE_LOCAL = /(.+)-(.+)-(.+)/" --> # 流程控制语句实现逻辑 正则匹配当前本地日期 捕获年月日
        <!--#if expr="($2 = '03') && ($3 != /0[1-3]/)" --> # 嵌套的if 正则跟字符串比较?
            3月3日之后
        <!--#else -->
            默认
        <!--#endif -->
    <!--#endif -->
    

    SSI与页面布局

    页面布局中一些相对固定的模块,可以通过include的方式包含到页面中。
    通常情况下,上面有 4个区域是不经常变动的:Header、Left Nav、Nav Trail 和 Footer。

    <body>
    <!--#include virtual="ssi/header.ssi"--> # 把头部模块包含进来
        <div id="Main">
            <div id="LeftNav"><!--#include virtual="ssi/nav_left.ssi"--></div> # 左侧导航模块包含进来
            <div id="RightNav"><!--#include virtual="ssi/nav_right.ssi"--></div> # ~右侧导航模块include进来
            <div id="Content">
                <div id="NavTrail"><!--#include virtual="ssi/nav_trail.ssi"--></div> # 面包屑模块include进来
            <p>Hello SSI</p>
            </div>
        </div>
        <!--#include virtual="ssi/footer.ssi"--> # 页脚模块include进来
    </body>
    
    
    <!--#set var="protocol" value="" --> # 设置变量protocol初始值 
    <!--#if expr="$HTTPS != /ON/" --> # 若环境变量$HTTPS 开启,则设置变量protocol的值
        <!--#set var="protocol" value="http://${SERVER_NAME}" -->
    <!--#endif -->
    <!--#set var="protocols" value="https://${SERVER_NAME}" --> # 设置变量 变量名比较长的话用大括号包起来比较清晰,易于解析。
    
    # 根据请求的路径 高亮显示相应的栏目链接
    <ul>
        <li class="TopLink">
            <a class="left-nav-overview" href="<!--#echo var='protocol' -->/ ">IBM</a>
        </li>
        <li class="PrimaryLink<!--#if expr='$DOCUMENT_URI = //systems/cn//' -->-Highlight<!--#endif -->">
            <a class="left-nav" href="<!--#echo var='protocol' -->/systems/cn/">Systems</a>
        </li>
        <li class="PrimaryLink<!--#if expr='$DOCUMENT_URI = //contact/index.html/' -->-Highlight<!--#endif -->">
            <a class="left-nav" href="<!--#echo var='protocols' -->/contact/index.html">联系我们</a>
        </li>
    </ul>
    

    Nav Trail 又叫做 Breadcrumb,中文里我们叫做“当前位置”。在页面上,根据当前页面所在不同,在这个地方会有提示访问者当前所在的位置。如果在每个页面都存在这个提示的话,编辑起来会很麻烦。但现在可以使用 SSI 解决这个问题,只要在每个页面的这个位置 include 一个 SSI 文件就可以了,当前所在位置的工作交给 SSI 来完成。

    <!--#set var="protocol" value="" --> # 设置变量protocol初始值
    <!--#if expr="$HTTPS != /ON/" --> # 若url是 https:// 安全访问模式
        <!--#set var="protocol" value="http://${SERVER_NAME}" --> # 设置变量 protocol的值
    <!--#endif -->
    <!--#set var="protocols" value="https://${SERVER_NAME}" --> 
    
    # 设置一系列变量值 当前位置的链接和文本
    <!--#set var="NavTrailLink1" value="" -->
    <!--#set var="NavTrailLinkName1" value="" -->
    
    <!--#set var="NavTrailLink2" value="" -->
    <!--#set var="NavTrailLinkName2" value="" -->
    
    <!--#set var="NavTrailLink3" value="" -->
    <!--#set var="NavTrailLinkName3" value="" -->
    
    #  设置值时是多重if嵌套
    <!--#if expr="$DOCUMENT_URI = //bnn// && $DOCUMENT_URI != //bnn/index.html/" --> # 若是访问/bnn/下非index.html页面
        <!--#set var="NavTrailLink1" value="${protocol}/bnn/" --> # 设置一级文本和链接变量值
        <!--#set var="NavTrailLinkName1" value="BNN" -->
    
        <!--#if expr="$DOCUMENT_URI = //bnn/books// && $DOCUMENT_URI != //bnn/books/index.html/" --> # 若是访问/bnn/books/下非index.html页面
            <!--#set var="NavTrailLink2" value="${protocol}/bnn/books/" --> # 设置二级文本和链接变量值 如此类推
            <!--#set var="NavTrailLinkName2" value="图书馆" -->
    
        <!--#elif expr="$DOCUMENT_URI = //bnn/food// && $DOCUMENT_URI != //bnn/food/index.html/" -->
            <!--#set var="NavTrailLink2" value="${protocol}/bnn/food/" -->
            <!--#set var="NavTrailLinkName2" value="好吃的" -->
    
            <!--#if expr="$DOCUMENT_URI = //bnn/food/strawberry// && $DOCUMENT_URI != //bnn/food/strawberry/index.html/" -->
                <!--#set var="NavTrailLink3" value="${protocol}/bnn/food/strawberry/" -->
                <!--#set var="NavTrailLinkName3" value="草莓" -->
            <!--#endif -->
    
        <!--#endif -->
    <!--#endif -->
    
    # 输出当前位置时也是多重if嵌套
    <img alt="" class="display-img" height="6" src="//www.ibm.com/i/c.gif" width="1" />
    <!--#if expr="$NavTrailLink1" -->
        <a class="bctl" href="<!--#echo var='NavTrailLink1' -->"><!--#echo var="NavTrailLinkName1" --></a><span class="bct">&nbsp;&gt;&nbsp;</span>
        <!--#if expr="$NavTrailLink2" -->
            <a class="bctl" href="<!--#echo var='NavTrailLink2' -->"><!--#echo var="NavTrailLinkName2" --></a><span class="bct">&nbsp;&gt;&nbsp;</span>
            <!--#if expr="$NavTrailLink3" -->
                <a class="bctl" href="<!--#echo var='NavTrailLink3' -->"><!--#echo var="NavTrailLinkName3" --></a><span class="bct">&nbsp;&gt;&nbsp;</span>
            <!--#endif -->
        <!--#endif -->
    <!--#endif -->
    

    SSI指令小结

    语法: <!--#directive [parm=value] --> ,指令包括:

    • config:设置日期格式等,如:(<!--#config timefmt="%B %Y" -->)
    • echo:打印变量值 (<!--#echo var="VARIABLE_NAEM" -->)
    • exec:用来执行服务器端的命令
    • include:文件包含 (<!--#include virtual="file-name" -->)
    • flastmod:输出指定文件最后修改时间(<!--#flastmod file="filename.shtml" -->)
    • fsize:输出指定文件的大小(<!--#fzie file="filename.shtml" -->)
    • printenv:打印所有环境变量(<!--#printenv -->)
    • set:设置或修改变量 (<!--#set var="foo" value="Bar" -->)
    • if elif endif else:创建条件分支
  • 相关阅读:
    推荐下自己的开源框架:DataMapFramework
    真的能无师自通吗?JAVA学习指导系列
    再回首,工作的第一个十年
    2个DataSet中的数据传递问题,请高手们多多指教。
    数据结构小结
    CDQZ_Training 2012524 词编码
    PowerDesigner显示Comment注释
    DDD基本元素
    使用FluorineFx.NET更新FMS中的SharedObject
    如何取消页面缓存
  • 原文地址:https://www.cnblogs.com/stephenykk/p/5393890.html
Copyright © 2011-2022 走看看