序:一直断断续续的写着这个东西。无奈网上对于这方面的文章很少,所以这里都是就谈谈个人制作过程中经验想法,仅供参考,如果有什么错误尽请指正。本意旨在抛砖引玉,希望有这方面经验的朋友共同探讨。这里主要对个人思路的阐述,文字表达能力不是很好,见谅。
设计这个系统的初衷是想程序和界面分离,那么在建立一个网站的时候只需要设计一套界面,加入系统提供的标签成为模板导入系统就完成,而且在内容组织及界面定义上有极高的自由度。制作者不需要接触任何程序。通过安装插件,在DW可视化编辑环境下,插入模板标签也象插入HTML代码一样轻松简单.如下面:
<cms:loop target='sort' name='allsort' cols='' rows='0'>
<table width="400" border="0" cellspacing="1" cellpadding="0" style="border: 1px solid #999999;">
<tr>
<td bgcolor="#CCCCCC"><a href="<cms:urlsort>"><cms:sortname></a></td>
</tr>
<tr>
<td height="1" bgcolor="#666666"></td>
</tr>
<tr>
<td bgcolor="#CCCCCC">
<cms:loop taget='article' cols='10' name='articel'>
·<a href="<cms:urltitle>"><cms:title lenth='20'></a><font color="#666666"><cms:date></font><br>
</cms:loop name='articel'>
</td>
</tr>
</table>
</cms:loop name='allsort'>
这是一个循环显示所有子栏目及子栏目下10条记录的模板文件其中<cms:***>即系统提供的标签。根据这些标签,生成文件效果如下:
我们经常在浏览网站时看到 ***.com/news/2004/06/08/2314342.html类似的网站,这个就是网站的后台管理程序根据数据库类容生成的静态html页面,其优点我就不用说了。我们的目的就是利用asp利用摸板页内容动态生成html等格式网页文件。其中主要用到的方法就是替换了。也就是程序据把摸板文件里定义好的标记替换成数据库里具体记录的内容并生成相应的页面文件。
模板替换的难点在于循环及嵌套循环。(如很常见的2级页面循环当前栏目的所有子栏目,每个栏目下又循环10条最新记录,有些有每行横向循环2-3个栏目等)以及循环中的参数传递及分析。其他的不过是个replace而已,通过一次有一次的从写代码,总结。这里我把创建页面的过程分为以下几个步骤。
这里画了个大流程图
今天就主要说说第一步:创建队列
1)什么使创建队列,就是告诉创建程序,我有哪些文件需要创建。然后程序根据创建队列集合逐个创建文件,这样一来使得生成文件这一行为非常对象化了.因为我们在管理内容是可能有以下动作,创建所有栏目及文章,创建某个栏目,创建某个栏目及文章,创建某个文章,创建我选定栏目或文章.引入了队列这个概念后我们只需要将需要创建的内容ID组合起来交给函数自己去做就行了.而无需去知道是什么行为.如我添加完一条记录后调用函数并送过去文章的栏目路径及文章ID,程序就根据这些数字逐个去创建相应的文件了.那么就算以后在扩展功能上也有很大的余地.如这样的形式 21,22,23,-201(这些数字主要是栏目和文章ID)为什么有负数呢?请往下看。
2)那么收到这个队列集合后呢,就该逐个根据ID好到数据库中去找该记录的相关参数来创建页面了。这里使用每自动刷新一次页面创建一个文件,应为如果一次要创建的文件很多的话一次性程序长期大量的占用CPU是不科学的,而且很可能脚本超时。
这里先张贴两个代码片断再做讲解。
<!-- #include file="_INC/Conn.asp" -->
Const spaceTime = 8
DIM FSO,WTO,FDER,SERVER_NAME
DBOpen()
Set FSO = Server.CreateObject("Scripting.FileSystemObject")
Call Main()
Set FSO = Nothing
DBClose()
'******************
'*******subs*******
'******************
DIM Global_Childs,Global_PageCutNum 'Global variables,used by morethan one function
Sub Main()
DIM rsPrv,sqlPrv,j,k,Come
DIM Alignment,cStep,Steps,StepArr,CurrentStep,PrvPageCutNum
Global_PageCutNum = Request("Page")
cStep = Request("cStep")
Steps = Request("Steps")
Alignment = Request("Queue")
'控制上页进度调显示
If Steps <> 0 Then
DIM percent
percent = Int(cStep/Steps*100)
Response.Write("<script>parent.percent.width='"&percent&"%'</script>")
End If
'#中断?
'判断创建过程是否完成
If Int(cStep) = Int(Steps) and Steps <> "" Then
PrintInfo("<font color=red>全部创建完毕:</font> 共创建网页文件 "&Session("totalfiles")&"个; 耗时 "& FormatNumber((timer()-Session("StartTime"))*1000,3)&"毫秒")
Session("totalfiles") = ""
Session("StartTime") = ""
Exit Sub
End If
'第一次没有接收到创建队列,默认为创建全部内容,创建全队列
If Alignment = "" Then Call Alignment_All()
'取得当前进度及值
If Steps = "" Then Steps = uBound(StepArr) + 1 'Run once only
If Session("totalfiles") = "" Then Session("totalfiles") = uBound(StepArr)
CurrentStep = StepArr(cStep)
Set StepArr = nothing
'根据ID值大于0为创建栏目,负数为创建文章页面文件
DIM SortID,Forder,StorePath,ParentPath,Templet
If Int(CurrentStep) > -1 Then
Set rsPrv = Conn.ExeCute("Select * From ["& OP_TABLE_CLASS& "] Where SortID="& CurrentStep)
SortID = rsPrv("SortID")
Templet = rsPrv("Templet")
Forder = rsPrv("ForderName") 'The sort's storepath just like it's fordername
Global_Childs = rsPrv("Childs")
ParentPath = rsPrv("ParentPath")
rsRemove(rsPrv)
If Global_PageCutNum = "" Then Call Creat_Forders(Forder)
'建立对象,调用创建文件主函数,并取得是分页与否参数
DIM myCreat,PageCutNum
Set myCreat = New Creat
myCreat.SortID = SortID
myCreat.Templet = Templet
myCreat.StorePath = Forder
myCreat.ParentPath = ParentPath
myCreat.reg = "<cms:loop>"'循环功能目前只定义在非终极页面中
myCreat.CreatClass()
PrvPageCutNum = myCreat.PageCutNum'判断是否进入分页流程
Set myCreat = Nothing
Else
'小于0为创建文章页面
DIM TempletSun,ID
'文章ID记录为负数,转换为正数
ID = Int(CurrentStep)*-1
Set rsPrv = Conn.ExeCute("Select A.ID,S.TempletSun From ["& OP_TABLE_ARTICLE &"] A inner join ["& OP_TABLE_CLASS &"] S on S.SortID=A.SortID where A.ID="&ID)
TempletSun = rsPrv("TempletSun")
rsRemove(rsPrv)
Call CreatFinal(ID,TempletSun)
End If
'#中断
'参数传递进入下一次创建
Response.Write("<body onUnload='Creating.submit()'>")
Response.Write("<form method='post' name='Creating'><input type='hidden' name='Come' value='"&Come&"'><input type='hidden' name='cStep' value='"&cStep&"'><input name='Steps' type='hidden' value='"&Steps&"'><input type='hidden' name='Page' value='"&PrvPageCutNum&"'><input type='hidden' name='Queue' value='"&Alignment&"'></form>")
Response.Write("<meta http-equiv='refresh' content="&spaceTime&";url='LIB_Creat.asp'>")
代码最后部分,这里输出一些HTML内容。
先看Response.Write("<meta http-equiv='refresh' content="&spaceTime&";url='LIB_Creat.asp'>")
也就是程序执行到最后输出一断自动刷新页面的html代码。
再看Response.Write("<body onUnload='Creating.submit()'>")
这里定义了页面在卸载的时候提交下面表单,本来可以通过querystring传递的,但以前看书上写好像伊最大只能传递256K数据还是多少,记不清了。所以这里通过form表单post方法提交,同时如果创建队列太长,如我网站有大小栏目10个有1000篇文章,某天我根新了模板要重新创建所有内容,呵呵,一次执行来完成,是不太可能的。这就象接力赛一样,一棒一棒往下传。一个文件一个文件的创建。这还有一个好处就是可以同时可以给用户返回当前进度和具体的创建过程中信息(可以看后么截图)如:如果用户某个模板标签定义错误,导致创建页面失败,等,这些信息都应该反馈给用户。
还有一点,以前参考看过一些类似的系统,也是通过刷新页面这种方式,但页面不停的刷新导致屏幕不停的闪烁,所以这里我把通过Creat.asp中长宽为0的iframe连接LIB_Creat.asp文件。解决创建是页面闪烁问题。
总结:将要创建的文件ID号组成队列结合交由创建函数对其逐个生成,队列中正数表示栏目ID负数表示文章ID。为了保证资源的占用,通过每刷新一次页面访问该函数来生成文件。