绝对原创MVC模式ASP框架
常常自问,ASP框架模式(MVC)实现就那么难吗?众多.NET,PHP,Java框架摆在你的面前,你还有必要研究ASP框架么?没错,随着Web技术不断发展,什么SNS,WEB2.0应用系统应运而生,换位思考一下,为何我们不使用这些个理念来完善或者说来挖掘出ASP自身更大的潜力呢?他们能办到的为何ASP不能办到呢?是因为ASP语言本身的局限性一直阻碍着我们,还是因为我们没有一个更好的设计模式?应该什么都不是!我在这里可以很负责的说,ASP一定能够做到而且还应该做得非常的好!框架说明:
1.框架还没有完全开发好,只是完善了部分功能,不过我在这里会不定期的更新直至整个框架的完成。
2.框架统一采用Javascript脚本语言开发,因为本人还是不习惯VBScript的语法,实在抱歉。
3.框架采用MVC模式,动态生成缓存文件以供系统调用。
语法说明:
1.不再使用关键字var来定义变量了,而是采用$来直接定义变量,比如$sitename,因为实在太喜欢PHP中的$符合了,够简洁。
2.常量采用全大写的格式,比如$_SGLOBAL
好了,暂时就这些,以后如有其它约定还会在这里补充的。
MVC系统肯定有它的框架结构,我的框架结构如下:
./
admin - 后台管理目录
data - 系统缓存,数据库备份目录
/tpl_cache 模板生成的缓存都在这里了
image - 图像目录
source - 核心文件目录
template - 模板目录
/default 系统默认模板都在这里了(这个是必须要有的目录)
/image 模板相关的图像目录
/blue 自定义模板目录(自己都可以随意定义,可能还有好多其他的模板目录)
/...(其它的一些自定义模板目录就不一一举例了,具体格式可以参照default模板)
common.asp 网站公共文件
config.asp 网站配置文件
index.asp 网站入口文件
好,框架结构定下来了,不会有大的变动,只会有很细微的变动,也会在这里随时更新的。
下面我先把完成的一些代码贴出来。
common.asp - 网站公共文件
<%@LANGUAGE="JAVASCRIPT" CODEPAGE="936"%>
<%
IN_RICHMOND = true;
X_VER = '1.0';
X_RELEASE = '20090401';
//创建FSO对象
FSO = Server.CreateObject('Scripting.FileSystemObject');
$_SGLOBAL = {
};
%>
<!--#include file = './config.asp'-->
<!--#include file = './source/function_common.asp'-->
<!--#include file = './source/function_template.asp'-->
<!--#include file = './source/class_database.asp'-->
<!--#include file = './source/class_data_grid.asp'-->
<%
%>
大家可以看到,首先是定义了网站的一些常量,其次包含了一些核心文件,比如公共函数库、模板、数据库、分页,后续可能还会加入更多这样的类库。
config.asp - 网站配置文件
<%
/**
* page build by Richmond 09-04-06
*/
//配置参数
$_SC = {
dbhost: '(local)',//服务器地址
dbuser: 'Richmond',//用户
dbpw: '******',//密码
dbname: 'database'//数据库
//...
};
$_SCONFIG = {
template: 'default'
};
%>
./source/function_common.asp 网站公共函数库
<%
/**
* page build by Richmond 09-04-06
*/
//测字符串实际长度
String.prototype.tlength = function(){
$arr = this.match(/[^\x00-\xff]/ig);
return this.length + ($arr == null ? 0 : $arr.length);
}
//字符串左取
String.prototype.left = function($num, $mode){
if(!/\d+/.test($num)) return(this);
$str = this.substr(0, $num);
if(!$mode) return $str;
$n = $str.tlength()-$str.length;
$num -= parseInt($n/2);
return this.substr(0, $num);
}
//字符串右取
String.prototype.right = function($num, $mode){
if(!/\d+/.test($num)) return(this);
$str = this.substr(this.length-$num);
if(!$mode) return $str;
$n = $str.tlength()-$str.length;
$num -= parseInt($n/2);
return this.substr(this.length-$num);
}
//字符串包含
String.prototype.get_count = function($str, $mode){
return eval('this.match(/(' + $str + ')/g' + ($mode ? 'i' : '') + ').length');
}
//字符串去除两端空字符
String.prototype.trim = function(){
return this.replace(/(^\s*)|(\s*$)/g,'');
}
String.prototype.ltrim = function(){
return this.replace(/(^\s*)/g, '');
}
String.prototype.rtrim = function(){
return this.replace(/(\s*$)/g, '');
}
function empty($obj) {
return !(String($obj) != '' && String($obj) != 'undefined');
}
function is_array($obj) {
return $obj.constructor == Array;
}
//判断字符串是否存在
function strexists($haystack, $needle) {
return $haystack.indexOf($needle) != -1;
}
//判断文件是否存在
function file_exists($name) {
if(FSO.FileExists(Server.MapPath($name))) {
return true;
} else {
return false;
}
return false;
}
//判断目录是否存在
function folder_exists($path) {
if(FSO.FolderExists(Server.MapPath($path))) {
return true;
} else {
return false;
}
return false;
}
//读取文件内容
function sreadfile($name) {
if(!file_exists($name)) {
return false;//文件不存在
} else {
$result = FSO.OpenTextFile(Server.MapPath($name)).ReadAll();
if($result == '') return false;//文件为空
return $result;
}
return false;
}
//写入文件
function swritefile($filename, $writetext) {
$op = FSO.OpenTextFile(Server.MapPath($filename), 2, true);
if($op.Write($writetext)) {
return true;
} else {
//这里可以是写入日志
return false;
}
}
//SQL ADDSLASHES
function saddslashes($string) {
}
//取消HTML代码
function shtmlspecialchars($string) {
$unallowed = {
'&': '&',
'"': '"',
'<': '<',
'>': '>'
};
for($p in $unallowed){
$string = $string.replace(eval('/'+$p+'/g'), $unallowed[$p]);
}
return $string;
}
//数据库连接
function dbconnect() {
}
//获取到表名
function tname($name) {
}
//对话框
function showmessage() {
}
//判断提交是否正确
function submitcheck($val) {
}
//检查是否登录
function checklogin() {
}
//模板调用
function template($name) {
if(strexists($name, '/')) {//自定义路径
$tpl = $name;
} else {//系统配置路径
$tpl = 'template/'+$_SCONFIG['template']+'/' + $name;
}
parse_template($tpl);//解析输出到模板
}
%>
最关键的是模板解析文件./source/function_templace.asp,可以这么说,网上没有找到一个很合适的模板解析文件,只有实现思路,代码都写得非常乱,没有一个很好的体系,请看我的代码:
<%
/**
* page build by Richmond 09-04-06
*/
$_SGLOBAL['i'] = 0;
$_SGLOBAL['block_search'] = new Array();
$_SGLOBAL['block_replace'] = new Array();
function parse_template($tpl) {
//包含模板
$_SGLOBAL['sub_tpls'] = new Array($tpl);
$tplfile = './'+$tpl+'.htm';
$objfile = './data/tpl_cache/'+$tpl.replace(/\//g,'_')+'.asp';
//read
if(!file_exists($tplfile)) {
$tplfile = $tplfile.replace('/'+$_SCONFIG['template']+'/', '/default/');
}
$template = sreadfile($tplfile);
if(empty($template)) {
Response.Write('Template file : '+tplfile+' Not found or have no access!');
Response.End();
}
//模板
$template = $template.replace(/\<\!\-\-\{template\s+(+)\}\-\-\>/ig, readtemplate);
//处理子页面中的代码
$template = $template.replace(/\<\!\-\-\{template\s+(+)\}\-\-\>/ig, readtemplate);
//ASP代码
$template = $template.replace(/\<\!\-\-\{eval\s+(.+?)\s*\}\-\-\>/ig, evaltags);
//开始处理
//变量
$template = $template.replace(/\<\!\-\-\{(.+?)\}\-\-\>/ig, '$1');
$template = $template.replace(/([\n\r]+)\t+/g, '$1');
$template = $template.replace(/(\$\'\"\$\x7f-\xff]+)\.(*)/ig, "$1['$2']");
$template = $template.replace(/\{(\$\'\"\$\.\x7f-\xff]+)\}/ig, '\<\%=$1\%\>');
$template = $template.replace(/((\$*)(\[\$\x7f-\xff]+\])*)/, addquote);
$template = $template.replace(/\<\%\=\<\%\=((\$*)(\[\$\x7f-\xff]+\])*)\%\>\%\>/ig, addquote);
//逻辑
//替换
if(!empty($_SGLOBAL['block_search'])) {
for($i=1;$i<$_SGLOBAL['block_search'].length;$i++){
$template = $template.replace($_SGLOBAL['block_search'][$i], $_SGLOBAL['block_replace'][$i]);
}
}
//换行
$template = $template.replace(/ \?\>[\n\r]*\<\? /ig, ' ');
//write
if(!swritefile($objfile, $template)) {
// Response.Write('File: '+objfile+' can not be write!');
// Response.End();
}
}
function addquote() {
$str = '\<\%='+arguments+'\%\>';
return $str.replace(/\[(+)\]/ig, "['$1']");
}
function evaltags() {
$_SGLOBAL['i']++;
$search = '\<\!\-\-EVAL_TAG_'+$_SGLOBAL['i']+'\-\-\>';
$_SGLOBAL['block_search'][$_SGLOBAL['i']] = $search;
$_SGLOBAL['block_replace'][$_SGLOBAL['i']] = '\<\% '+stripvtags(arguments)+' \%\>';
return $search;
}
function stripvtags($expr, $statement) {
if(typeof $statement == 'undefined') $statement = '';
$expr = $expr.replace(/\<\%\=(.+?)\%\>/i, 'Response.Write($1);');
return $expr+$statement;
}
//读取模板
function readtemplate() {
$name = arguments;
$tpl = strexists($name,'/')?$name:'template/'+$_SCONFIG['template']+'/'+$name;
$tplfile = './'+$tpl+'.htm';
if(!file_exists($tplfile)) {
$tplfile = $tplfile.replace('/'+$_SCONFIG['template']+'/', '/default/');
}
$content = sreadfile($tplfile);
return $content;
}
%>
注意,模板解析还有部分功能没有完善,比如逻辑、循环等,不过我会随时更新的。
现在举个简单的例子来证明:
首先在./template/default/目录下建立两个.htm模板文件,一个名为index.htm,一个名为sub.htm。
index.htm代码是这样的,
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" C>
<META NAME="Author" C>
<META NAME="Keywords" C>
<META NAME="Description" C>
</HEAD>
<BODY>
<h1>{$_SCONFIG['sitename']}</h1>
<!--{eval Response.Write("hello1");}-->
<!--{eval Response.Write("hello2");}-->
<!--{eval Response.Write("hello3");}-->
<!--{template sub}-->
</BODY>
</HTML>
注意看到上面<!--{template sub}-->了吗,它是调用子模板sub.htm,也就是说模板中再调用一次模板,这在使用包含公共文件时候非常有用的。
sub.htm
<!--{eval Response.Write("这个是sub.htm子模板");}-->
现在回到./index.asp页面中来,添加如下代码:
<!--#include file = 'common.asp'-->
<%
template('index');
%
好,现在系统会在./data/tpl_cache目录下面生成一个缓存文件template_default_index.asp,这个文件名是有含义的,template表示模板,default表示模板的目录,index就是模板了。我们可以打开该模板查看一下到底是些什么代码:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
<META NAME="Generator" C>
<META NAME="Author" C>
<META NAME="Keywords" C>
<META NAME="Description" C>
</HEAD>
<BODY>
<h1><%=$_SCONFIG['sitename']%></h1>
<% Response.Write("hello1"); %>
<% Response.Write("hello2"); %>
<% Response.Write("hello3"); %>
<% Response.Write("这个是sub.htm子模板"); %>
</BODY>
</HTML>
很好,我们已经成功把模板中的数据转换成ASP的代码了。以后的实现思路是这样的,系统在加载时会先读取缓存文件,如果缓存文件不存在就重新解析一下模板而后生成,从而避免每次都要解析生成模板,但前提是你的模板文件没有做过任何修改,如若不然,那只有删除缓存文件重新生成了,时间仓促,可能有些地方有疏漏或错误,但是这个思路和实现的模式能否给大家对ASP的未来带来一丝希望将拭目以待。 请问在这里如何才能编辑帖子呢? 来支持一下ASP 原帖由 jlmqq 于 2009-4-17 16:23 发表 http://bbs.51js.com/images/common/back.gif
请问在这里如何才能编辑帖子呢?
你发的帖子右下角有“ 编辑 引用 报告 回复 ”的 提示审核后的贴子是无法编辑的。 楼主的想法不错,期待早日实现能看到demo 最新搞的一个网站,也是采用这个模式开发的
http://www.0000114.com 高手们,指点一二 还是不能编辑啊,提示信息:对不起,管理员设置了需要对发帖进行审核,您没有权力编辑已通过审核的帖子,请返回。
页:
[1]